From dbff6b1fe437815ec40ea7122f5619f4414f02ac Mon Sep 17 00:00:00 2001 From: P L Sai Krishna Date: Fri, 29 May 2015 13:00:04 +0530 Subject: [PATCH] xilisf: Created new minor version. This patch deprecates the xilisf_v5_2 and created new minor version xilisf_v5_3. Signed-off-by: P L Sai Krishna --- lib/sw_services/xilisf/data/xilisf.mld | 58 + lib/sw_services/xilisf/data/xilisf.tcl | 191 ++ .../xilisf_atmel_buffer_rdwr_example.c | 556 +++++ .../xilisf_atmel_rdwr_polled_example.c | 331 +++ .../xilisf_atmel_read_write_example.c | 515 +++++ .../examples/xilisf_atmel_spr_example.c | 786 +++++++ .../examples/xilisf_intel_otp_rdwr_example.c | 511 +++++ .../xilisf_intel_rdwr_polled_example.c | 425 ++++ .../xilisf_intel_read_write_example.c | 655 ++++++ .../examples/xilisf_intel_spr_example.c | 925 ++++++++ .../examples/xilisf_qspips_stm_intr_example.c | 864 ++++++++ .../xilisf_qspips_stm_polled_example.c | 727 ++++++ .../examples/xilisf_spips_sst_intr_example.c | 717 ++++++ .../xilisf_spips_sst_polled_example.c | 480 ++++ .../examples/xilisf_stm_quad_flash_example.c | 972 ++++++++ .../examples/xilisf_stm_rdwr_polled_example.c | 383 ++++ .../examples/xilisf_stm_read_write_example.c | 585 +++++ .../xilisf/examples/xilisf_stm_spr_example.c | 754 +++++++ .../xilisf_winbond_quad_flash_example.c | 849 +++++++ .../xilisf_winbond_rdwr_polled_example.c | 355 +++ .../xilisf_winbond_read_write_example.c | 555 +++++ .../examples/xilisf_winbond_spr_example.c | 754 +++++++ lib/sw_services/xilisf/src/Makefile | 89 + lib/sw_services/xilisf/src/include/xilisf.h | 1045 +++++++++ .../xilisf/src/include/xilisf_atmel.h | 268 +++ .../xilisf/src/include/xilisf_intelstm.h | 365 +++ lib/sw_services/xilisf/src/xilisf.c | 1956 +++++++++++++++++ lib/sw_services/xilisf/src/xilisf_erase.c | 597 +++++ lib/sw_services/xilisf/src/xilisf_read.c | 978 +++++++++ lib/sw_services/xilisf/src/xilisf_spr.c | 411 ++++ lib/sw_services/xilisf/src/xilisf_write.c | 975 ++++++++ 31 files changed, 19632 insertions(+) create mode 100755 lib/sw_services/xilisf/data/xilisf.mld create mode 100755 lib/sw_services/xilisf/data/xilisf.tcl create mode 100644 lib/sw_services/xilisf/examples/xilisf_atmel_buffer_rdwr_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_atmel_rdwr_polled_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_atmel_read_write_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_atmel_spr_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_intel_otp_rdwr_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_intel_rdwr_polled_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_intel_read_write_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_intel_spr_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_qspips_stm_intr_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_qspips_stm_polled_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_spips_sst_intr_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_spips_sst_polled_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_stm_quad_flash_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_stm_rdwr_polled_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_stm_read_write_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_stm_spr_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_winbond_quad_flash_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_winbond_rdwr_polled_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_winbond_read_write_example.c create mode 100644 lib/sw_services/xilisf/examples/xilisf_winbond_spr_example.c create mode 100644 lib/sw_services/xilisf/src/Makefile create mode 100644 lib/sw_services/xilisf/src/include/xilisf.h create mode 100644 lib/sw_services/xilisf/src/include/xilisf_atmel.h create mode 100644 lib/sw_services/xilisf/src/include/xilisf_intelstm.h create mode 100644 lib/sw_services/xilisf/src/xilisf.c create mode 100644 lib/sw_services/xilisf/src/xilisf_erase.c create mode 100644 lib/sw_services/xilisf/src/xilisf_read.c create mode 100644 lib/sw_services/xilisf/src/xilisf_spr.c create mode 100644 lib/sw_services/xilisf/src/xilisf_write.c diff --git a/lib/sw_services/xilisf/data/xilisf.mld b/lib/sw_services/xilisf/data/xilisf.mld new file mode 100755 index 00000000..325d341e --- /dev/null +++ b/lib/sw_services/xilisf/data/xilisf.mld @@ -0,0 +1,58 @@ +############################################################################### +# +# Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 2.04a sdm 08/01/11 Added new parameter for Numonyx quad flash devices. +# 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS. +# Added support to SST flash. +# 3.00a srt 02/06/13 Changed the serial flash family options to include +# Spansion flash (CR 696379). +# 5.1 sb 12/23/14 Added Micron to the serial flash family options. +# +############################################################################## + +OPTION psf_version = 2.1; + +BEGIN LIBRARY xilisf + OPTION drc = isf_drc; + OPTION copyfiles = all; + OPTION REQUIRES_OS = (standalone xilkernel); + OPTION APP_LINKER_FLAGS = "-Wl,--start-group,-lxilisf,-lxil,-lgcc,-lc,--end-group"; + OPTION desc = "Xilinx In-system and Serial Flash Library"; + OPTION VERSION = 5.3; + OPTION NAME = xilisf; + PARAM name = serial_flash_family, desc = "Indicates the Serial Flash family type. Enter 1 for ATMEL. 2 for INTEL. 3 for STM (M25PXX). 4 for Winbond. 5 for Spansion / Micron. 6 for SST Flash", type = int, default = 1; + PARAM name = serial_flash_interface, desc = "Indicates the Serial Flash Interface. Enter 1 for AXI SPI. 2 for PS SPI. 3 for PS QSPI.", type = int, default = 1; +END LIBRARY diff --git a/lib/sw_services/xilisf/data/xilisf.tcl b/lib/sw_services/xilisf/data/xilisf.tcl new file mode 100755 index 00000000..7e2d1f13 --- /dev/null +++ b/lib/sw_services/xilisf/data/xilisf.tcl @@ -0,0 +1,191 @@ +############################################################################### +# +# Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 2.01a sdm 06/17/10 Updated to support axi_spi +# 2.02a sdm 09/24/10 updated to use Tcl commands instead of unix commands +# 2.03a sdm 04/17/11 Updated to support axi_quad_spi +# 2.04a sdm 08/01/11 Added new parameter for Numonyx quad flash devices. +# 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS. +# Added support to SST flash. +# 3.02a srt 05/13/13 Removed compiler errors when not selecting proper +# interface for Zynq. (CR 716451) +# +############################################################################## + +#--------------------------------------------- +# ISF_drc - check system configuration and make sure +# all components to run ISF are available. +#--------------------------------------------- + +proc isf_drc {libhandle} { + puts "Running DRC for XilIsf library... \n" + + # find the list of xps or opb spi cores + set sw_processor [hsi::get_sw_processor] + set processor [hsi::get_cells [common::get_property HW_INSTANCE $sw_processor]] + + set spi_periphs_list [get_spi_periphs $processor] + + if { [llength $spi_periphs_list] == 0 } { + set cpuname [common::get_property NAME $processor] + error "ERROR: No SPI core is addressable from processor $cpuname. \ + XilIsf library requires a SPI Core \n" + return + } +} + +proc get_spi_periphs {processor} { + set periphs_list [::hsi::utils::get_proc_slave_periphs $processor] + set spi_periphs_list {} + + global spi_periphs_name_list + set spi_periphs_name_list {} + + foreach periph $periphs_list { + set periphname [common::get_property IP_NAME $periph] + if {$periphname == "xps_spi" + || $periphname == "opb_spi" + || $periphname == "xps_insystem_flash" + || $periphname == "axi_spi" + || $periphname == "axi_quad_spi" + || $periphname == "ps7_spi" + || $periphname == "ps7_qspi"} { + lappend spi_periphs_list $periph + lappend spi_periphs_name_list $periphname + } + } + + return $spi_periphs_list +} + +#-------- +# Check the following h/w requirements for XilIsf: +#-------- +proc isf_hw_drc {libhandle spi_list} { +} + + +# SPI hw requirements +proc isf_spi_hw_drc {libhandle spi} { + +} + + +proc generate {libhandle} { + +} + + +#------- +# post_generate: called after generate called on all libraries +#------- +proc post_generate {libhandle} { + xgen_opts_file $libhandle + +} + +#------- +# execs_generate: called after BSP's, libraries and drivers have been compiled +# This procedure builds the libisf.a library +#------- +proc execs_generate {libhandle} { + +} + + +proc xgen_opts_file {libhandle} { + + # Open xparameters.h file + set file_handle [::hsi::utils::open_include_file "xparameters.h"] + + # ----------------------------- + # Generate Flash options + # ----------------------------- + puts $file_handle "/* Xilinx EDK In-system and Serial Flash Library (XilIsf) User Settings */" + set serial_flash_family [common::get_property CONFIG.serial_flash_family $libhandle] + puts $file_handle "\#define XPAR_XISF_FLASH_FAMILY $serial_flash_family" + + set serial_flash_interface [common::get_property CONFIG.serial_flash_interface $libhandle] + set ifaceselect 0 + set ps7qspi 0 + global spi_periphs_name_list + foreach periph $spi_periphs_name_list { + if {$periph == "axi_spi" || $periph == "axi_quad_spi" + || $periph == "opb_spi" + || $periph == "xps_insystem_flash" + || $periph == "xps_spi"} { + if {$serial_flash_interface == 1} { + puts $file_handle "\#define XPAR_XISF_INTERFACE_AXISPI 1" + set ifaceselect 1 + } + } elseif {$periph == "ps7_spi" && + $serial_flash_interface == 2} { + puts $file_handle "\#define XPAR_XISF_INTERFACE_PSSPI 1" + set ifaceselect 1 + } elseif {$periph == "ps7_qspi" && + $serial_flash_interface == 3} { + puts $file_handle "\#define XPAR_XISF_INTERFACE_PSQSPI 1" + set ifaceselect 1 + } elseif {$periph == "ps7_qspi"} { + set ps7qspi 1 + } + } + + if {$ps7qspi == 1 && $ifaceselect == 0} { + puts "WARN: Improper Flash Interface from BSP Settings!!!! Defaulting on 'ps7_qspi' interface" + puts $file_handle "\#define XPAR_XISF_INTERFACE_PSQSPI 1" + } + + puts $file_handle "" + close $file_handle + + # Copy the include files to the include directory + set srcdir [file join src include] + set dstdir [file join .. .. include] + + # Create dstdir if it does not exist + if { ! [file exists $dstdir] } { + file mkdir $dstdir + } + + # Get list of files in the srcdir + set sources [glob -join $srcdir *.h] + + # Copy each of the files in the list to dstdir + foreach source $sources { + file copy -force $source $dstdir + } +} diff --git a/lib/sw_services/xilisf/examples/xilisf_atmel_buffer_rdwr_example.c b/lib/sw_services/xilisf/examples/xilisf_atmel_buffer_rdwr_example.c new file mode 100644 index 00000000..1f66d4d0 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_atmel_buffer_rdwr_example.c @@ -0,0 +1,556 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xilisf_atmel_buffer_rdwr_example.c +* +* +* This file contains a design example using the Xilinx In-system and Serial +* Flash Library (XilIsf). This example shows the Buffer Write, Buffer to Page +* Program with Built-in Erase, Page to Buffer Transfer and Buffer Read features. +* +* This example +* - Writes to a SRAM page buffer using Buffer Write feature +* - Erase a Page and data is transferred to this page from the SRAM page buffer +* using the Buffer to Page Program with Built-in Erase feature. +* - Transfers the data to a SRAM Page using Page to Buffer Transfer feature. +* - Reads back the Buffer that is written using the Buffer Read feature and +* compares the data. +* +* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash +* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is 264 for +* Default addressing mode and 256 in Power-of-2 addressing mode. +* +* For AT45DB161D/AT45DB321D the Bytes Per Page (ISF_PAGE_SIZE) is 528 for +* Default addressing mode and 512 in Power-Of-2 addressing mode. +* +* For AT45DB642D the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default +* addressing mode and 1024 in Power-Of-2 addressing mode. +* +* The ISF_PAGE_SIZE should be defined by the user according to the Device used. +* +* For further details of each device refer to the Spartan-3AN Serial Flash User +* Guide and data sheets of Atmel AT45XXXD . +* +* This example has been tested with the In-system Flash Memory available on the +* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- ---------------------------------------------------
+* 1.00a ksu/sdm  03/22/08 First release
+* 2.00a ktn  	 11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   	 08/05/14 Registering to Xilisf Interrupt handler
+*		      	  instead of driver handler.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Serial Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Page size of the Serial Flash. + */ +#define ISF_PAGE_SIZE 264 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define TEST_ADDRESS 0xA3600 + +#define ISF_TEST_BYTE 0x28 /* Test Byte offset value written to Serial + Flash */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(); + +static int SetupInterruptSystem(XSpi *SpiPtr); + +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that the + * are initialized to zero each time the program runs. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/*****************************************************************************/ +/** +* +* Main function to execute the Atmel Serial Flash Buffer Read/Write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main(void) +{ + int Status; + u16 Index; + XIsf_BufferWriteParam BufferWriteParam; + XIsf_BufferToFlashWriteParam BufferToFlashWriteParam; + XIsf_FlashToBufTransferParam FlashToBufTransferParam; + XIsf_BufferReadParam BufferReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + Status = XSpi_Start(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Initialize the In-system and Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Set the + * - SRAM page buffer number where the data is to be written. + * - Byte offset within SRAM page buffer where the data is to be written + * - The number of bytes to be written. + * - The Write Buffer with the data to be written. + */ + BufferWriteParam.BufferNum = XISF_PAGE_BUFFER1; + BufferWriteParam.ByteOffset = 0; + BufferWriteParam.NumBytes = ISF_PAGE_SIZE; + BufferWriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + BufferWriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Write to SRAM Page buffer. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_BUFFER_WRITE, (void*) &BufferWriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + + /* + * Set the + * - SRAM page buffer number from where the data is to be written. + * - Page Address in the Serial Flash where the data is to be written. + */ + BufferToFlashWriteParam.BufferNum = XISF_PAGE_BUFFER1; + BufferToFlashWriteParam.Address = TEST_ADDRESS; + + /* + * Perform Erase then Write to Serial Flash from the SRAM page buffer. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_BUF_TO_PAGE_WRITE_WITH_ERASE, + (void*) &BufferToFlashWriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready to accept next command. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - SRAM page buffer number to which the data is to be read. + * - Set the Page Address from where the data is to be transferred. + */ + FlashToBufTransferParam.BufferNum = XISF_PAGE_BUFFER1; + FlashToBufTransferParam.Address = TEST_ADDRESS; + + /* + * Transfer data from the Serial Flash to the SRAM page buffer. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_PAGE_TO_BUF_TRANS, + (void*) &FlashToBufTransferParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready to accept next command. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - SRAM page buffer number where the data is to be read. + * - Byte offset within SRAM page buffer where the data is to be read. + * - The number of bytes to be read. + * - The Read Buffer to which with the data is to be read. + */ + BufferReadParam.BufferNum = XISF_PAGE_BUFFER1; + BufferReadParam.ByteOffset = 0; + BufferReadParam.NumBytes = ISF_PAGE_SIZE; + BufferReadParam.ReadPtr = ReadBuffer; + + /* + * Read data from SRAM page buffer. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_BUFFER_READ, (void*) &BufferReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Atmel Serial Flash is ready to accept next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int IsfWaitForFlashNotBusy() +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[1]; + if(StatusReg & XISF_SR_IS_READY_MASK) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that the SPI + * can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_atmel_rdwr_polled_example.c b/lib/sw_services/xilisf/examples/xilisf_atmel_rdwr_polled_example.c new file mode 100644 index 00000000..ec3d08a7 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_atmel_rdwr_polled_example.c @@ -0,0 +1,331 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xilisf_atmel_rdwr_polled_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf) with the Spi driver in polled mode of operation. This example +* shows the Erase, Read and Write features. +* +* This example +* - Erases a Page +* - Writes to the erased Page +* - Reads back the Page that is written and compares the data +* +* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash +* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is +* 264 for Default addressing mode and 256 in Power-of-2 addressing mode. +* +* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is +* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode. +* +* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default +* addressing mode and 1024 in Power-Of-2 addressing mode. +* +* The ISF_PAGE_SIZE should be defined by the user according to the Device used. +* +* For further details of each device refer to the Spartan-3AN Serial Flash User +* Guide and data sheets of Atmel AT45XXXD . +* +* This example has been tested with the In-System Flash Memory available on the +* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- --- -------- ---------------------------------------------------
+* 1.00a sdm 04/02/08 First release
+* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
+*		     to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xilisf.h" /* Serial Flash Library header file */ + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID + +/* + * The following constant defines the slave select signal that is used to + * select the Serial Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Page size of the Serial Flash. + */ +#define ISF_PAGE_SIZE 264 + +/* + * Address within the page of the Serial Flash to perform Erase, Write and Read + * operations. + */ +#define TEST_ADDRESS 0xA2400 +#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. + */ +static XIsf Isf; +static XSpi Spi; + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/*****************************************************************************/ +/** +* +* Main function to execute the Atmel Serial Flash Read/Write polled example. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + u16 Index; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + u32 Address; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the SPI driver so that the device is enabled. + */ + Status = XSpi_Start(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Disable Global interrupt to use the Spi driver in polled mode + * operation. + */ + XSpi_IntrGlobalDisable(&Spi); + + /* + * Initialize the In-system and Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = TEST_ADDRESS; + + /* + * Perform the Page Erase operation. + */ + Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - The number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the Read operation. + */ + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Compare the Data Read with the Data Written to the Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Serial Flash is ready to accept next command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int IsfWaitForFlashNotBusy() +{ + int Status; + u8 StatusReg; + u8 ReadBuffer[2]; + + while(1) { + + /* + * Get the Status Register. + */ + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if(StatusReg & XISF_SR_IS_READY_MASK) { + break; + } + } + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_atmel_read_write_example.c b/lib/sw_services/xilisf/examples/xilisf_atmel_read_write_example.c new file mode 100644 index 00000000..29460fa6 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_atmel_read_write_example.c @@ -0,0 +1,515 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xilisf_atmel_read_write_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf). This example shows the Erase, Read and Write features. +* +* This example +* - Erases a Page +* - Writes to the erased Page +* - Reads back the Page that is written and compares the data. +* +* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash +* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is +* 264 for Default addressing mode and 256 in Power-of-2 addressing mode. +* +* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is +* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode. +* +* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default +* addressing mode and 1024 in Power-Of-2 addressing mode. +* +* The ISF_PAGE_SIZE should be defined by the user according to the Device used. +* +* For further details of each device refer to the Spartan-3AN Serial Flash User +* Guide and data sheets of Atmel AT45XXXD . +* +* This example has been tested with the In-System Flash Memory available on the +* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- ---------------------------------------------------
+* 1.00a mta/ksu  03/20/08 First release
+* 2.00a ktn  	 11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   	 08/05/14 Registering to Xilisf Interrupt handler
+*		      	  instead of driver handler.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * select the Serial Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Page size of the Serial Flash. + */ +#define ISF_PAGE_SIZE 264 + +/* + * Address within the page of the Serial Flash to perform Erase, Write and Read + * operations. + */ +#define TEST_ADDRESS 0xA2400 +#define ISF_TEST_BYTE 0x30 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(); + +static int SetupInterruptSystem(XSpi *SpiPtr); + +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/*****************************************************************************/ +/** +* +* Main function to execute the Atmel Serial Flash Read/Write example. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + u16 Index; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + u32 Address; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + Status = XSpi_Start(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Initialize the In-system and Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = TEST_ADDRESS; + + /* + * Perform the Page Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - The number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the Read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the Data Read with the Data Written to the Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Serial Flash is ready to accept next command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int IsfWaitForFlashNotBusy() +{ + int Status; + u8 StatusReg; + u8 ReadBuffer[2]; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if(StatusReg & XISF_SR_IS_READY_MASK) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that it's ready to use + * specify the device ID that is generated in xparameters.h. + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device. + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that the SPI + * can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_atmel_spr_example.c b/lib/sw_services/xilisf/examples/xilisf_atmel_spr_example.c new file mode 100644 index 00000000..76238d59 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_atmel_spr_example.c @@ -0,0 +1,786 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xilisf_atmel_spr_example.c +* +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf). This example shows all the features related to Sector +* Protection. +* +* This example +* - Writes to the Sector Protection Register +* - Reads the Sector Protection Register and compares with the data that was +* written +* - Erases the Sector Protection Register +* - Erases a Page and writes the data to the Page +* - Enables the Sector Protection so that all the sectors are Write protected +* - Erases a Page (This should not happen as the Sectors are Write protected +* - Reads back the Page that is written and compares the data. +* +* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash +* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is +* 264 for Default addressing mode and 256 in Power-of-2 addressing mode. +* +* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is +* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode. +* +* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default +* addressing mode and 1024 in Power-Of-2 addressing mode. +* +* The ISF_PAGE_SIZE should be defined by the user according to the Device used. +* +* For further details of each device refer to the Spartan-3AN Serial Flash User +* Guide and data sheets of Atmel AT45XXXD . +* +* This example has been tested with the In-System Flash Memory available on the +* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------------
+* 1.00a mta/ksu  03/20/08 First release
+* 1.00a ktn 	 09/08/09 Updated this example such that every SPR write should
+*			  be preceded by an erase as per the atmel datasheet.
+* 2.00a ktn  	 11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   	 08/05/14 Registering to Xilisf Interrupt handler
+*		      	  instead of driver handler.
+*
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * select the Serial Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Page size of the Serial Flash. + */ +#define ISF_PAGE_SIZE 264 + +/* + * Address within the page of the Serial Flash to perform Erase, Write and Read + * operations. + */ +#define TEST_ADDRESS 0xA2400 +#define ISF_TEST_BYTE 0x36 /* Test Byte offset value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(); + +static int SetupInterruptSystem(XSpi *SpiPtr); + +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer. */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer. */ + +/*****************************************************************************/ +/** +* +* Main function to execute the Atmel Serial Flash SPR example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main(void) +{ + int Status; + u16 Index; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + Status = XSpi_Start(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Initialize the In-system and Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Perform the SPR erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_ERASE, NULL); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the SPR read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the values read back from the SPR with the values written + * during SPR erase operation. Return if error. + */ + for(Index = 0; Index < Isf.NumOfSectors; Index++) { + if((ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] & 0xFF) != + 0xFF) { + return XST_FAILURE; + } + } + + /* + * Prepare the values to be written to the Sector Protect Register + * (SPR). + */ + for(Index = 0; Index < Isf.NumOfSectors; Index++) { + WriteBuffer[Index] = 0x00; + } + + /* + * Perform the SPR write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the SPR read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the values read back from the SPR with the values written + * during SPR write operation. Return if error. + */ + for(Index = 0; Index < Isf.NumOfSectors; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != 0x00) { + return XST_FAILURE; + } + } + + /* + * Perform the SPR erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_ERASE, NULL); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + ErrorCount = 0; + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the SPR read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the values read from the SPR, are all 0xFF after performing + * the SPR erase operation. + */ + for(Index = XISF_CMD_SEND_EXTRA_BYTES; Index < (Isf.NumOfSectors + + XISF_CMD_SEND_EXTRA_BYTES); Index++) { + if(ReadBuffer[Index] != 0xFF) { + return XST_FAILURE; + } + } + + /* + * Perform the SP disable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SP_DISABLE, NULL); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Page Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, TEST_ADDRESS); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - The number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = TEST_ADDRESS; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the SP enable operation. This should enable protection for + * all sectors since a SP erase operation has been performed earlier. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SP_ENABLE, NULL); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Page Erase operation. The Page Erase operation should not + * work since SP is enabled. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, TEST_ADDRESS); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the SP disable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SP_DISABLE, NULL); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Serial Flash is ready. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = TEST_ADDRESS; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the read operation. The values read should be same as the + * values written earlier. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Serial Flash is ready to accept next command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int IsfWaitForFlashNotBusy() +{ + int Status; + u8 StatusReg; + u8 ReadBuffer[2]; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if(StatusReg & XISF_SR_IS_READY_MASK) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that it's ready to use + * specify the device ID that is generated in xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specific real mode so that the SPI + * can cause interrupts thru the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_intel_otp_rdwr_example.c b/lib/sw_services/xilisf/examples/xilisf_intel_otp_rdwr_example.c new file mode 100644 index 00000000..e737cf8b --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_intel_otp_rdwr_example.c @@ -0,0 +1,511 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_intel_otp_rdwr_example.c +* +* This file contains a design example using the Xilinx In-system and Serial +* Flash Library (XilIsf). This example shows the One-Time Programmable (OTP) +* Read/Write features. +* +* This example +* - Writes a Byte to OTP region +* - Reads back the Byte written to the OTP region and compares the data +* +* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33) +* on a S3A-DSP starter kit. For further details about the S33 Flash device refer +* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets. +* +* +* @note +* +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  03/24/08 First release
+* 2.00a ktn  11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes to be written to the OTP area of the Serial Flash. + */ +#define ISF_OTP_WRITE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_OTP_TEST_ADDRESS 0x0225; +#define ISF_TEST_BYTE 0x30 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_OTP_WRITE_SIZE + XISF_OTP_RDWR_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_OTP_WRITE_SIZE + XISF_OTP_RDWR_EXTRA_BYTES]; /* Read Buffer */ +u8 WriteBuffer[ISF_OTP_WRITE_SIZE]; /* Write Buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Intel OTP Read/Write Flash example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the In-system and Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the OTP region of the Serial Flash for the + * Write/Read operations. + */ + Address = ISF_OTP_TEST_ADDRESS; + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the OTP region of the Serial Flash where the data is + * to be written. + * - The number of bytes to be written to the Serial Flash, this is + * always 1 as only 1 byte can be written. + * - Write Buffer which contains the data to be written to the OTP + * region of the Serial Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_OTP_WRITE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * the OTP region of the Serial Flash. + */ + WriteParam.WritePtr[BYTE1] = ISF_TEST_BYTE; + + /* + * Perform the OTP Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_OTP_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the OTP region of the Serial Flash where the data is to + * be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_OTP_WRITE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the OTP read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_OTP_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + if(ReadBuffer[BYTE1 + XISF_OTP_RDWR_EXTRA_BYTES] != + (u8)(ISF_TEST_BYTE)) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Intel serial Flash is ready to accept the next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the Status Register of the Serial Flash and +* waits till the WIP bit of the Status Register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for any errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + * If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + + /* + * If there were errors return XST_FAILURE. + */ + if (StatusReg & (XISF_SR_PROG_FAIL_MASK | + XISF_SR_ERASE_FAIL_MASK)) { + return XST_FAILURE; + } + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that + * the SPI can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_intel_rdwr_polled_example.c b/lib/sw_services/xilisf/examples/xilisf_intel_rdwr_polled_example.c new file mode 100644 index 00000000..55428f54 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_intel_rdwr_polled_example.c @@ -0,0 +1,425 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_intel_rdwr_polled_example.c +* +* This file contains a design example using the Xilinx In-system and Serial +* Flash Library (XilIsf) with the Spi driver in polled mode of operation. +* This example shows the Sector Protection Register Read, Sector Protection +* Register Write, Sector Erase, Read and Write features. +* +* This example +* - Disables the Sector Protection for all the Sectors +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data. +* +* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33) +* on a S3A-DSP starter kit. For further details about the S33 Flash device refer +* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 04/02/08 First release
+* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
+*		     to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xilisf.h" /* Serial Flash Library header file */ + + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XSpi Spi; + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Intel Serial Flash Read/Write polled example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the SPI driver so that device is enabled. + */ + XSpi_Start(&Spi); + + /* + * Disable Global interrupt to use the Spi driver in polled mode + * operation. + */ + XSpi_IntrGlobalDisable(&Spi); + + /* + * Initialize the In-system and Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * The following code Disables the Sector Protection for all the Blocks + * in the Intel Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is Not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the Sector Protection Register. + */ + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Clear all the Block protection bits in the Sector Protection + * Register. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & + (~(XISF_SR_BLOCK_PROTECT_MASK)); + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + + /* + * The following code Erases a Sector in the Intel Serial Flash. + */ + + + /* + * Perform the Write Enable operation. + */ + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * The following code Writes data to a Page in the Intel Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * - Set the address within the Serial Flash where the data is to be + * written. + * - Set the number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * The following code Reads data from a Page in the Intel Serial Flash. + */ + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the read operation. + */ + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Intel Serial Flash is ready to accept next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the Status Register of the Serial Flash and +* waits till the WIP bit of the Status Register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + + /* + * If there were errors return XST_FAILURE. + */ + if (StatusReg & (XISF_SR_PROG_FAIL_MASK | + XISF_SR_ERASE_FAIL_MASK)) { + return XST_FAILURE; + } + break; + } + } + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_intel_read_write_example.c b/lib/sw_services/xilisf/examples/xilisf_intel_read_write_example.c new file mode 100644 index 00000000..0445cb11 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_intel_read_write_example.c @@ -0,0 +1,655 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_intel_read_write_example.c +* +* This file contains a design example using the Xilinx In-system and Serial +* Flash Library (XilIsf). This example shows the Sector Protection Register +* Read, Sector Protection Register Write, Sector Erase, Read and Write features. +* +* This example +* - Disables the Sector Protection for all the Sectors +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data. +* +* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33) +* on a S3A-DSP starter kit. For further details about the S33 Flash device refer +* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  03/17/08 First release
+* 2.00a ktn  11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+*
+* 
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Intel Serial Flash Read/Write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the In-system and Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * The following code Disables the Sector Protection for all the Blocks + * in the Intel Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is Not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the Sector Protection Register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Clear all the Block protection bits in the Sector Protection + * Register. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & + (~(XISF_SR_BLOCK_PROTECT_MASK)); + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + + /* + * The following code Erases a Sector in the Intel Serial Flash. + */ + + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * The following code Writes data to a Page in the Intel Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * - Set the address within the Serial Flash where the data is to be + * written. + * - Set the number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * The following code Reads data from a Page in the Intel Serial Flash. + */ + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Intel Serial Flash is ready to accept next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the Status Register of the Serial Flash and +* waits till the WIP bit of the Status Register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is in progress. + */ + while(TransferInProgress); + + /* + * Check if there are any errors in the transaction. + */ + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + + /* + * If there were errors return XST_FAILURE. + */ + if (StatusReg & (XISF_SR_PROG_FAIL_MASK | + XISF_SR_ERASE_FAIL_MASK)) { + return XST_FAILURE; + } + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that + * the SPI can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_intel_spr_example.c b/lib/sw_services/xilisf/examples/xilisf_intel_spr_example.c new file mode 100644 index 00000000..31c791c3 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_intel_spr_example.c @@ -0,0 +1,925 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_intel_spr_example.c +* +* This file contains a design example using the Xilinx In-system and Serial +* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector +* Protection, Read and Write features. + +* This example +* - Disables the Sector Protection for all the Sectors +* - Erases a Sector +* - Writes to a Page within the erased Sector +* - Enables the Sector Protection so that all the sectors are Write protected +* - Erases the Sector (This should not happen as the Sectors are Write protected +* - Reads the Status Register and checks if the Erase Fail Flag is set +* - Clears the Status Register Fail Flags +* - Reads back the Page that is written and compares the data. +* +* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33) +* on a S3A-DSP starter kit. For further details about the S33 Flash device refer +* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  03/17/08 First release
+* 2.00a ktn  11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include "xspi.h" /* SPI device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Serial Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the Serial Flash. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; + +/* + * The following variable tracks any errors that occur during interrupt + * processing. + */ +static int ErrorCount; + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; +u8 WriteBuffer[ISF_PAGE_SIZE]; + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Intel Serial Flash SPR example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + u8 StatusReg; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the sector protection register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Clear all the block protection bits in the sector protection register + * value read above. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & + (~(XISF_SR_BLOCK_PROTECT_MASK)); + + /* + * Write this value to the sector protection register to disable the + * sector protection. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * - Set the address within the Serial Flash where the data is to be + * written. + * - Set the number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the sector protection register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Set all the block protection bits in the sector protection register + * value read above and write it back to the sector protection register. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] | + (XISF_SR_BLOCK_PROTECT_MASK); + + /* + * Enable the sector protection. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. This should not work as writes to + * the Serial Flash are disabled. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is in progress. + */ + while(TransferInProgress); + + /* + * Check if there are any errors in the transaction. + */ + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the erase fail flag is set in the status register. This flag + * should be set as a sector erase operation was attempted when sector + * protection was enabled. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_ERASE_FAIL_MASK) == 0) { + return XST_FAILURE; + } + /* + * Clear the status register fail flags in the Serial Flash status + * register. + */ + TransferInProgress = TRUE; + Status = XIsf_Ioctl(&Isf, XISF_IOCTL_CLEAR_SR_FAIL_FLAGS); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is in progress. + */ + while(TransferInProgress); + + /* + * Check if there are any errors in the transaction. + */ + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the erase fail flag is clear in the status register. This + * flag should be clear as a 'Clear SR Fail Flags' command has been + * executed. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_ERASE_FAIL_MASK) != 0) { + return XST_FAILURE; + } + + /* + * Read the sector protection register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Clear all the block protection bits in the sector protection register + * value read above and write it back to the sector protection register + * to disable sector protection for all sectors. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & + ~(XISF_SR_BLOCK_PROTECT_MASK); + + /* + * Disable the sector protection. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * The following code Reads data from a Page in the Intel Serial Flash. + */ + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the STM serial Flash is ready to accept next command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and + waits till the WIP bit of the status register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is in progress. + */ + while(TransferInProgress); + + /* + * Check if there are any errors in the transaction. + */ + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + * If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specific real mode so that + * the SPI can cause interrupts thru the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_qspips_stm_intr_example.c b/lib/sw_services/xilisf/examples/xilisf_qspips_stm_intr_example.c new file mode 100644 index 00000000..bc3dbfd6 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_qspips_stm_intr_example.c @@ -0,0 +1,864 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_qspips_flash_intr_example.c +* +* +* This file contains a design example using the XILISF Library in +* interrupt mode with a serial FLASH device. This examples performs +* some transfers in Auto mode and Manual start mode, to illustrate the modes +* available. +* The hardware which this example runs on, must have a serial FLASH (Numonyx +* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been +* tested with the Numonyx Serial Flash (N25Q128). +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  srt 06/20/12 First release
+* 1.01  srt 04/26/13 Modified Erase function to perform Write Enable operation
+*		     for each sector erase.
+* 1.01  srt 08/28/13 Fixed the CR 731919, by setting the proper QSPI options.
+* 5.0   sb  08/05/14 Added support for greater than 128MB flash operations.
+*
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /**< EDK generated parameters */ +#include "xscugic.h" /**< Interrupt controller device driver */ +#include "xil_exception.h" +#include "xil_printf.h" +#include /**< Serial Flash Library header file */ + +/************************** Constant Definitions *****************************/ +/** @name Device ID's + * + * @{ + */ +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define QSPI_INTR_ID XPAR_XQSPIPS_0_INTR +/*@}*/ + +/** + * The following constants define the offsets within a FlashBuffer data + * type for each kind of data. Note that the read data offset is not the + * same as the write data because the QSPI driver is designed to allow full + * duplex transfers such that the number of bytes received is the number + * sent and received. + */ +#define DATA_OFFSET 4 /**< Start of Data for Read/Write */ +#define DUMMY_OFFSET 4 /**< Dummy byte offset for fast, dual + and quad reads */ +#define DUMMY_SIZE 1 /**< Number of dummy bytes for fast, + dual and quad reads */ + +/** + * The following constants specify the page size, sector size, and number of + * pages and sectors for the FLASH. The page size specifies a max number of + * bytes that can be written to the FLASH with a single transfer. + */ +#define NUM_PAGES 0x10000 /**< Number of Pages in the flash */ +#define PAGE_SIZE 256 /**< Page Size for Read/Write Operation */ + +/** + * Number of flash pages to be written. + */ +#define PAGE_COUNT 16 /**< Number of Pages for + Read/Write Operation */ + +/** + * Flash address to which data is to be written. + */ +#define TEST_ADDRESS 0x00080000 /**< Test Address in the flash */ +#define UNIQUE_VALUE 0x05 /**< Unique Value for Test */ + +/** + * The following constants specify the max amount of data and the size of the + * the buffer required to hold the data and overhead to transfer the data to + * and from the FLASH. + */ +#define MAX_DATA PAGE_COUNT * PAGE_SIZE /**< Max Data Calculated by + multiplying Page count and Page Size*/ + +/** + * The following constant defines the slave select signal that is used to + * to select the FLASH device on the QSPI bus, this signal is typically + * connected to the chip select of the device + */ +#define FLASH_QSPI_SELECT 0x00 + +#define INTR_MODE 1 /**< Interrupt Mode Enable */ + +#define FAST_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Fast Read*/ +#define DUAL_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Dual Read */ +#define QUAD_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Quad Read */ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int QspiSetupIntrSystem(XScuGic *IntcInstancePtr, + XQspiPs *QspiInstancePtr, u16 QspiIntrId); + +static void QspiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 QspiIntrId); + +void XilIsf_Handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount); + +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount); +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command); +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command); +int QspiFlashIntrExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr, + u16 QspiDeviceId, u16 QspiIntrId); +u32 SectorMask(u32 SectorSize); + +/************************** Variable Definitions *****************************/ + +/** + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XScuGic IntcInstance; +static XQspiPs QspiInstance; +static XIsf Isf; + +/** + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile int TransferInProgress; + +/** + * The following variable tracks any errors that occur during interrupt + * processing + */ +int ErrorCount; + +/** + * The following variable allows a test value to be added to the values that + * are written to the FLASH such that unique values can be generated to + * guarantee the writes to the FLASH were successful + */ +int Test = 5; + +/** + * The following variables are used to read and write to the eeprom and they + * are global to avoid having large buffers on the stack + */ +u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE]; +u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET]; /**< Write Buffer */ +u8 IsfWriteBuffer[PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];/**< IsfWrite Buffer + used in XilISF Initialization */ + + + +/** + * The following defines are for dual flash stacked mode interface. + */ +#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /**< Fast Quad Read output */ +#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /**< 1 Dummy Byte between + address and return data */ + +#define DUAL_STACK_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \ + LQSPI_CR_1_DUMMY_BYTE | \ + LQSPI_CR_FAST_QUAD_READ)/**< Fast Quad Read output */ + +#define DUAL_QSPI_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \ + XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \ + LQSPI_CR_1_DUMMY_BYTE | \ + LQSPI_CR_FAST_QUAD_READ)/**< Fast Quad Read output */ +/*****************************************************************************/ +/** +* +* Main function to call the QSPI Flash example. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("QSPI FLASH Interrupt Example Test \r\n"); + + /* + * Run the Qspi Interrupt example. + */ + Status = QspiFlashIntrExample(&IntcInstance, &QspiInstance, + QSPI_DEVICE_ID, QSPI_INTR_ID); + if (Status != XST_SUCCESS) { + xil_printf("QSPI FLASH Interrupt Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran QSPI FLASH Interrupt Example Test\r\n"); + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* The purpose of this function is to illustrate how to use the XQspiPs +* device driver in interrupt mode. This function writes and reads data +* from a serial FLASH. +* +* @param IntcInstancePtr is the instance of the interrupt +* @param QspiInstancePtr is the Pointer to the qspi driver instance +* @param QspiDeviceId is the Device ID of qspi +* @param QspiIntrId is the interrupt ID for QSPI driver +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* +* This function calls other functions which contain loops that may be infinite +* if interrupts are not working such that it may not return. If the device +* slave select is not correct and the device is not responding on bus it will +* read a status of 0xFF for the status register as the bus is pulled up. +* +*****************************************************************************/ +int QspiFlashIntrExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr, + u16 QspiDeviceId, u16 QspiIntrId) +{ + int Status; + u8 *BufferPtr; + u8 UniqueValue; + int Count; + int Page; + XQspiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */ + u32 Options; + + /* + * Lookup the device configuration in the temporary CROM table. Use this + * configuration info down below when initializing this component. + */ + ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId); + if (ConfigPtr == NULL) { + return XST_DEVICE_NOT_FOUND; + } + + Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr, + ConfigPtr->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Set the QSPI options + */ + Options = XQSPIPS_FORCE_SSELECT_OPTION | + XQSPIPS_MANUAL_START_OPTION | + XQSPIPS_HOLD_B_DRIVE_OPTION; + Status = XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr, + Options, XISF_SPI_PRESCALER); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) { + /* + * Enable two flash memories, Shared bus (NOT separate bus), + * L_PAGE selected by default + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + DUAL_STACK_CONFIG_WRITE); + } + + if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) { + /* + * Enable two flash memories on separate buses + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + DUAL_QSPI_CONFIG_WRITE); + } + + + /* Initialize the XILISF Library */ + XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT, + IsfWriteBuffer); + + + + XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE); + + /* + * Connect the Qspi device to the interrupt subsystem such that + * interrupts can occur. This function is application specific + */ + Status = QspiSetupIntrSystem(IntcInstancePtr, QspiInstancePtr, + QspiIntrId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the QSPI that will be called from the + * interrupt context when an QSPI status occurs, specify a pointer to + * the QSPI driver instance as the callback reference so the handler is + * able to access the instance data + */ + XIsf_SetStatusHandler(&Isf, QspiInstancePtr, + (XQspiPs_StatusHandler) XilIsf_Handler); + + /* + * Initialize the write buffer for a pattern to write to the FLASH + * and the read buffer to zero so it can be verified after the read, + * the test value that is added to the unique value allows the value + * to be changed in a debug environment to guarantee + */ + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE; + Count++, UniqueValue++) { + WriteBuffer[Count] = (u8)(UniqueValue + Test); + } + memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); + + Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Write the data in the write buffer to the serial FLASH a page at a + * time, starting from TEST_ADDRESS + */ + for (Page = 0; Page < PAGE_COUNT; Page++) { + FlashWrite(&Isf, (Page * PAGE_SIZE) + TEST_ADDRESS, + PAGE_SIZE, XISF_WRITE); + } + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read + * command + */ + FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ); + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + + BufferPtr = ReadBuffer; + + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + + if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { + return XST_FAILURE; + } + } + + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read + * command + */ + + Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_FAST_READ); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + + BufferPtr = ReadBuffer; + + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + + if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { + return XST_FAILURE; + } + } + + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using DUAL IO + * Fast Read command + */ + Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_DUAL_OP_FAST_READ); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + + BufferPtr = ReadBuffer; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + + if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { + return XST_FAILURE; + } + } + + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using QUAD OP + * Fast Read command + */ + Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_QUAD_OP_FAST_READ); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + + BufferPtr = ReadBuffer; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + if (BufferPtr[Count] != (u8)(UniqueValue + Test)) { + return XST_FAILURE; + } + } + + QspiDisableIntrSystem(IntcInstancePtr, QspiIntrId); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function is the handler which performs processing for the QSPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of QSPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle QSPI interrupts but is +* application specific. +* +* @param CallBackRef is a reference passed to the handler. +* @param StatusEvent is the status of the QSPI . +* @param ByteCount is the number of bytes transferred. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XilIsf_Handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount) +{ + /* + * Indicate the transfer on the QSPI bus is no longer in progress + * regardless of the status event + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function writes to the serial FLASH connected to the QSPI interface. +* The FLASH contains a 256 byte write buffer which can be filled and then a +* write is automatically performed by the device. All the data put into the +* buffer must be in the same page of the device with page boundaries being on +* 256 byte boundaries. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to write data to in the FLASH. +* @param ByteCount contains the number of bytes to write. +* @param Command is the command used to write data to the flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command) +{ + XIsf_WriteParam WriteParam; + + int Status; + + WriteParam.Address = Address; + WriteParam.NumBytes = ByteCount; + WriteParam.WritePtr = WriteBuffer; + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, Command, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function reads from the serial FLASH connected to the +* QSPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to read data from in the FLASH. +* @param ByteCount contains the number of bytes to read. +* @param Command is the command used to read data from the flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command) +{ + XIsf_ReadParam ReadParam; + int Status; + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ByteCount; + ReadParam.ReadPtr = ReadBuffer; + if(Command == XISF_FAST_READ){ + ReadParam.NumDummyBytes = FAST_READ_NUM_DUMMY_BYTES; + } + else if(Command == XISF_DUAL_OP_FAST_READ){ + ReadParam.NumDummyBytes = DUAL_READ_NUM_DUMMY_BYTES; + } + else{ + ReadParam.NumDummyBytes = QUAD_READ_NUM_DUMMY_BYTES; + } + + /* + * Perform the Read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, Command, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function erases the sectors in the serial FLASH connected to the +* QSPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address of the first sector which needs to +* be erased. +* @param ByteCount contains the total size to be erased. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount) +{ + int Status; + int Sector; + u32 NumSect; + u32 SectorSize; + u32 NumSectors; + u32 Sector_Mask; + + SectorSize = Isf.SectorSize; + NumSectors = Isf.NumSectors; + + /* Get the sector mask value */ + Sector_Mask = SectorMask(SectorSize); + + /* + * If erase size is same as the total size of the flash, use bulk erase + * command + */ + if (ByteCount == (NumSectors * SectorSize)) { + + /* + * Perform the Bulk Erase operation. + */ + + TransferInProgress = TRUE; + Status = XIsf_Erase(InstancePtr, XISF_BULK_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there + * are any errors in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + } + + /* + * Calculate no. of sectors to erase based on byte count + */ + NumSect = ByteCount/SectorSize + 1; + + /* + * If ByteCount to k sectors, + * but the address range spans from N to N+k+1 sectors, then + * increment no. of sectors to be erased + */ + + if( ((Address + ByteCount) & Sector_Mask) == + ((Address + (NumSect * SectorSize)) & + Sector_Mask) ) { + NumSect++; + } + + /* + * If the erase size is less than the total size of the flash, use + * sector erase command + */ + for (Sector = 0; Sector < NumSect; Sector++) { + + /* + * Perform the Bulk Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there + * are any errors in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Address += SectorSize; + } + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system for an Qspi device. +* +* @param IntcInstancePtr is a pointer to the instance of the Intc device. +* @param QspiInstancePtr is a pointer to the instance of the Qspi device. +* @param QspiIntrId is the interrupt Id for an QSPI device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int QspiSetupIntrSystem(XScuGic *IntcInstancePtr, + XQspiPs *QspiInstancePtr, u16 QspiIntrId) +{ + int Status; + + XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */ + + Xil_ExceptionInit(); + + /* + * Initialize the interrupt controller driver so that it is ready to + * use. + */ + IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); + if (NULL == IntcConfig) { + return XST_FAILURE; + } + + Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, + IntcConfig->CpuBaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + IntcInstancePtr); + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + Status = XScuGic_Connect(IntcInstancePtr, QspiIntrId, + (Xil_ExceptionHandler)XQspiPs_InterruptHandler, + (void *)QspiInstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Enable the interrupt for the Qspi device. + */ + XScuGic_Enable(IntcInstancePtr, QspiIntrId); + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function disables the interrupts that occur for the Qspi device. +* +* @param IntcInstancePtr is the pointer to an INTC instance. +* @param QspiIntrId is the interrupt Id for an QSPI device. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void QspiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 QspiIntrId) +{ + /* + * Disable the interrupt for the QSPI device. + */ + XScuGic_Disable(IntcInstancePtr, QspiIntrId); + + /* + * Disconnect and disable the interrupt for the Qspi device. + */ + XScuGic_Disconnect(IntcInstancePtr, QspiIntrId); +} + +/*****************************************************************************/ +/** +* +* This function calculates the sector mask based upon the sector size value +* +* +* @param SectorSize is the size of the sector of the flash +* available on the board. +* +* @return will return the sector mask after calculation. +* +* @note None. +* +******************************************************************************/ +u32 SectorMask(u32 SectorSize){ + + u32 Mask; + + switch(SectorSize){ + case 0x10000: + Mask = 0xFFFF0000; + break; + + case 0x20000: + Mask = 0xFFFE0000; + break; + + case 0x40000: + Mask = 0xFFFC0000; + break; + + case 0x80000: + Mask = 0xFFF80000; + break; + + default: + break; + } + + return Mask; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_qspips_stm_polled_example.c b/lib/sw_services/xilisf/examples/xilisf_qspips_stm_polled_example.c new file mode 100644 index 00000000..12ceaf88 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_qspips_stm_polled_example.c @@ -0,0 +1,727 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_qspips_flash_polled_example.c +* +* +* This file contains a design example using the XILISF Library in +* interrupt mode with a serial FLASH device. This examples performs +* some transfers in Auto mode and Manual start mode, to illustrate the modes +* available. +* The hardware which this example runs on, must have a serial FLASH (Numonyx +* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been +* tested with the Numonyx Serial Flash (N25Q128). +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  srt 06/20/12 First release
+* 1.01  srt 04/26/13 Modified Erase function to perform Write Enable operation
+*		     for each sector erase.
+* 1.01  srt 08/28/13 Fixed the CR 731919, by setting the proper QSPI options.
+* 5.0   sb  08/05/14 Added support for greater than 128MB flash operations.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xscugic.h" /* Interrupt controller device driver */ +#include "xil_exception.h" +#include "xil_printf.h" +#include "xilisf.h" /* Serial Flash Library header file */ + +/************************** Constant Definitions *****************************/ +/** @name Device ID's + * + * @{ + */ +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define QSPI_INTR_ID XPAR_XQSPIPS_0_INTR +/*@}*/ + +/** + * The following constants define the offsets within a FlashBuffer data + * type for each kind of data. Note that the read data offset is not the + * same as the write data because the QSPI driver is designed to allow full + * duplex transfers such that the number of bytes received is the number + * sent and received. + */ +#define DATA_OFFSET 4 /**< Start of Data for Read/Write */ +#define DUMMY_OFFSET 4 /**< Dummy byte offset for fast, dual and quad + reads */ +#define DUMMY_SIZE 1 /**< Number of dummy bytes for fast, dual and + quad reads */ + +/** + * The following constants specify the page size and number of + * pages for the FLASH. The page size specifies a max number of + * bytes that can be written to the FLASH with a single transfer. + */ +#define NUM_PAGES 0x10000 /**< Number of Pages in the flash */ +#define PAGE_SIZE 256 /**< Page Size for Read/Write Operation */ + +/** + * Number of flash pages to be written. + */ +#define PAGE_COUNT 32 /**< Number of Pages for r/w Operation */ + +/** + * Flash address to which data is ot be written. + */ +#define TEST_ADDRESS 0x00090000 /**< Test Address in the flash */ +#define UNIQUE_VALUE 0x08 /**< Unique Value for Test */ + + +/** + * The following constants specify the max amount of data and the size of the + * the buffer required to hold the data and overhead to transfer the data to + * and from the FLASH. + */ +#define MAX_DATA PAGE_COUNT * PAGE_SIZE /**< Max Data Calculated by + multiplying Page count and Page Size */ + +/** + * The following constant defines the slave select signal that is used to + * to select the FLASH device on the QSPI bus, this signal is typically + * connected to the chip select of the device + */ +#define FLASH_QSPI_SELECT 0x00 /**< Interrupt Mode Enable */ + +#define FAST_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for + Fast Read */ +#define DUAL_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for + Dual Read */ +#define QUAD_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for + Quad Read */ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount); +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, + u8 Command); +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, + u8 Command); +int QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr, + u16 QspiDeviceId, u16 QspiIntrId); +static u32 SectorMask(u32 SectorSize); + +/************************** Variable Definitions *****************************/ + +/** + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XScuGic IntcInstance; +static XQspiPs QspiInstance; +static XIsf Isf; +static XQspiPs_Config *ConfigPtr; /**< Pointer to Configuration ROM data */ + +/** + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile int TransferInProgress; + +/** + * The following variable allows a test value to be added to the values that + * are written to the FLASH such that unique values can be generated to + * guarantee the writes to the FLASH were successful + */ +int Test_Polled = 7; + +/** + * The following variables are used to read and write to the eeprom and they + * are global to avoid having large buffers on the stack + */ +u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE]; +u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET]; /**< Write Buffer */ +u8 IsfWriteBuffer[PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];/**< IsfWrite Buffer + used in XilISF Initialization */ + +/** + * The following defines are for dual flash stacked mode interface. + */ +#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /**< Fast Quad Read output */ +#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /**< 1 Dummy Byte between + address and return data */ + +#define DUAL_STACK_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \ + LQSPI_CR_1_DUMMY_BYTE | \ + LQSPI_CR_FAST_QUAD_READ) /**< Fast Quad Read output */ + +#define DUAL_QSPI_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \ + XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \ + LQSPI_CR_1_DUMMY_BYTE | \ + LQSPI_CR_FAST_QUAD_READ) /**< Fast Quad Read output */ +/*****************************************************************************/ +/** +* +* Main function to call the QSPI Flash example. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("QSPI FLASH Polling Example Test \r\n"); + + /* + * Run the Qspi Interrupt example. + */ + Status = QspiFlashPollExample(&IntcInstance, &QspiInstance, + QSPI_DEVICE_ID, QSPI_INTR_ID); + if (Status != XST_SUCCESS) { + xil_printf("QSPI FLASH Polling Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran QSPI FLASH Polling Example Test\r\n"); + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** +* The purpose of this function is to illustrate how to use the XQspiPs +* device driver in interrupt mode. This function writes and reads data +* from a serial FLASH. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* +* This function calls other functions which contain loops that may be infinite +* if interrupts are not working such that it may not return. If the device +* slave select is not correct and the device is not responding on bus it will +* read a status of 0xFF for the status register as the bus is pulled up. +* +*****************************************************************************/ +int QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr, + u16 QspiDeviceId, u16 QspiIntrId) +{ + u8 *BufferPtr; + u8 UniqueValue; + int Count; + int Page; + int Status; + u32 Options; + + /* + * Lookup the device configuration in the temporary CROM table. Use this + * configuration info down below when initializing this component. + */ + ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId); + if (ConfigPtr == NULL) { + return XST_DEVICE_NOT_FOUND; + } + + Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr, + ConfigPtr->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the QSPI options + */ + Options = XQSPIPS_FORCE_SSELECT_OPTION | + XQSPIPS_MANUAL_START_OPTION | + XQSPIPS_HOLD_B_DRIVE_OPTION; + XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr, Options, + XISF_SPI_PRESCALER); + + if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) { + /* + * Enable two flash memories, Shared bus + * (NOT separate bus), L_PAGE selected by default + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + DUAL_STACK_CONFIG_WRITE); + } + + if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) { + /* + * Enable two flash memories on separate buses + */ + XQspiPs_SetLqspiConfigReg(QspiInstancePtr, + DUAL_QSPI_CONFIG_WRITE); + } + + /* Initialize the XILISF Library */ + XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT, + IsfWriteBuffer); + + /* + * Initialize the write buffer for a pattern to write to the FLASH + * and the read buffer to zero so it can be verified after the read, + * the test value that is added to the unique value allows the value + * to be changed in a debug environment to guarantee + */ + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE; + Count++, UniqueValue++) { + WriteBuffer[Count] = (u8)(UniqueValue + Test_Polled); + } + memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); + + + Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Write the data in the write buffer to the serial FLASH a page at a + * time, starting from TEST_ADDRESS + */ + + for (Page = 0; Page < PAGE_COUNT; Page++) { + Status = FlashWrite(&Isf, + (Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE, + XISF_QUAD_IP_PAGE_WRITE); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + } + + /****************************************************** + **********************NORMAL READ********************* + ******************************************************/ + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read + * command + */ + Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + BufferPtr = ReadBuffer; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { + return XST_FAILURE; + } + } + + + /****************************************************** + **********************FAST READ*********************** + ******************************************************/ + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read + * command + */ + Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, + XISF_FAST_READ); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + + BufferPtr = ReadBuffer; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { + return XST_FAILURE; + } + } + + + /****************************************************** + ******************DUAL OP FAST READ******************* + ******************************************************/ + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using DUAL OP + * Fast Read command + */ + Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, + XISF_DUAL_OP_FAST_READ); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + + BufferPtr = ReadBuffer; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + + if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { + return XST_FAILURE; + } + } + + /****************************************************** + ******************QUAD IO FAST READ******************* + ******************************************************/ + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using QUAD IO + * Fast Read command + */ + Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, + XISF_QUAD_OP_FAST_READ); + if(Status != XST_SUCCESS){ + return XST_FAILURE; + } + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + + BufferPtr = ReadBuffer; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + + + +/*****************************************************************************/ +/** +* +* This function writes to the serial FLASH connected to the QSPI interface. +* The FLASH contains a 256 byte write buffer which can be filled and then a +* write is automatically performed by the device. All the data put into the +* buffer must be in the same page of the device with page boundaries being on +* 256 byte boundaries. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to write data to in the FLASH. +* @param ByteCount contains the number of bytes to write. +* @param Command is the command used to write data to the flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, + u8 Command) +{ + XIsf_WriteParam WriteParam; + + int Status; + + WriteParam.Address = Address; + WriteParam.NumBytes = ByteCount; + WriteParam.WritePtr = WriteBuffer; + + /* + * Perform the Write operation. + */ + Status = XIsf_Write(&Isf, Command, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function reads from the serial FLASH connected to the +* QSPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to read data from in the FLASH. +* @param ByteCount contains the number of bytes to read. +* @param Command is the command used to read data from the flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command) +{ + XIsf_ReadParam ReadParam; + int Status; + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes ReadParam.NumDummyBytesto be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ByteCount; + ReadParam.ReadPtr = ReadBuffer; + if(Command == XISF_FAST_READ){ + ReadParam.NumDummyBytes = FAST_READ_NUM_DUMMY_BYTES; + } + else if(Command == XISF_DUAL_OP_FAST_READ){ + ReadParam.NumDummyBytes = DUAL_READ_NUM_DUMMY_BYTES; + } + else{ + ReadParam.NumDummyBytes = QUAD_READ_NUM_DUMMY_BYTES; + } + /* + * Perform the Read operation. + */ + Status = XIsf_Read(&Isf, Command, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function erases the sectors in the serial FLASH connected to the +* QSPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address of the first sector which needs to +* be erased. +* @param ByteCount contains the total size to be erased. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount) +{ + int Status; + int Sector; + u32 LqspiCr; + u32 NumSect; + u32 SectorSize; + u32 NumSectors; + u32 Sector_Mask; + /* + * Get the value of Sector Size and Number of Sectors for the flash + */ + SectorSize = Isf.SectorSize; + NumSectors = Isf.NumSectors; + + /* Get the sector mask value */ + Sector_Mask = SectorMask(SectorSize); + + /* + * If erase size is same as the total size of the flash, use bulk erase + * command + */ + if (ByteCount == (NumSectors * SectorSize)) { + +#ifdef XPAR_XQSPIPS_0_DEVICE_ID + if(ConfigPtr->ConnectionMode == + XQSPIPS_CONNECTION_MODE_STACKED){ + + /* + * Get the current LQSPI configuration register value + */ + LqspiCr = + XQspiPs_GetLqspiConfigReg(InstancePtr->SpiInstPtr); + /* + * Set selection to L_PAGE + */ + XQspiPs_SetLqspiConfigReg(InstancePtr->SpiInstPtr, + LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK)); + + /* + * Assert the Flash chip select. + */ + XQspiPs_SetSlaveSelect(InstancePtr->SpiInstPtr); + } +#endif /*XPAR_XQSPIPS_0_DEVICE_ID*/ + + /* + * Call Bulk erase + */ + Status = XIsf_Erase(InstancePtr, + XISF_BULK_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + +#ifdef XPAR_XQSPIPS_0_DEVICE_ID + /* + * If stacked mode, bulk erase second flash + */ + if(ConfigPtr->ConnectionMode == + XQSPIPS_CONNECTION_MODE_STACKED){ + + /* + * Get the current LQSPI configuration register value + */ + LqspiCr = + XQspiPs_GetLqspiConfigReg(InstancePtr->SpiInstPtr); + /* + * Set selection to U_PAGE + */ + XQspiPs_SetLqspiConfigReg(InstancePtr->SpiInstPtr, + LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK); + + /* + * Assert the Flash chip select. + */ + XQspiPs_SetSlaveSelect(InstancePtr->SpiInstPtr); + + + /* + * Call Bulk erase + */ + Status = XIsf_Erase(InstancePtr, + XISF_BULK_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + } +#endif /*XPAR_XQSPIPS_0_DEVICE_ID*/ + + return Status; + } + + /* + * Calculate no. of sectors to erase based on byte count + */ + NumSect = ByteCount/SectorSize + 1; + + /* + * If ByteCount to k sectors, + * but the address range spans from N to N+k+1 sectors, then + * increment no. of sectors to be erased + */ + + if( ((Address + ByteCount) & Sector_Mask) == + ((Address + (NumSect * SectorSize)) & + Sector_Mask) ) { + NumSect++; + } + + /* + * If the erase size is less than the total size of the flash, use + * sector erase command + */ + for (Sector = 0; Sector < NumSect; Sector++) { + + /* + * Perform the Sector Erase operation. + */ + Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Address += SectorSize; + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function calculates the sector mask based upon the sector size value +* +* +* @param SectorSize is the size of the sector of the flash +* available on the board. +* +* @return will return the sector mask after calculation. +* +* @note None. +* +******************************************************************************/ +u32 SectorMask(u32 SectorSize){ + + u32 Mask; + + switch(SectorSize){ + case 0x10000: + Mask = 0xFFFF0000; + break; + + case 0x20000: + Mask = 0xFFFE0000; + break; + case 0x40000: + Mask = 0xFFFC0000; + break; + + case 0x80000: + Mask = 0xFFF80000; + break; + + default: + break; + } + + return Mask; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_spips_sst_intr_example.c b/lib/sw_services/xilisf/examples/xilisf_spips_sst_intr_example.c new file mode 100644 index 00000000..e8a096e5 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_spips_sst_intr_example.c @@ -0,0 +1,717 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_spips_flash_intr_example.c +* +* +* This file contains a design example using the XILISF Library in +* interrupt mode with a serial FLASH device. This examples performs +* some transfers in Auto mode and Manual start mode, to illustrate the modes +* available. +* The hardware which this example runs on, must have a serial FLASH (Numonyx +* N25Q, Winbond W25Q, SST or Spansion S25FL) for it to run. This example has +* been tested with the SST Flash. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  srt 06/20/12 First release
+* 3.01  srt 03/03/13 Modified the flash write, erase and read logic.
+*		     Ensured flash blocks are unprotected befor a flash erase
+*		     or write operation. (CR 703816)
+* 3.02  srt 04/26/13 Modified Erase function to perform Write Enable operation
+*		     for each sector erase.
+* 5.0   sb  08/05/14 Registering to Xilisf Interrupt handler
+*	             instead of driver handler.
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xscugic.h" /* Interrupt controller device driver */ +#include "xil_exception.h" +#include "xil_printf.h" +#include + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define SPI_INTR_ID XPAR_XSPIPS_1_INTR + +/* + * The following constants define the offsets within a FlashBuffer data + * type for each kind of data. Note that the read data offset is not the + * same as the write data because the SPI driver is designed to allow full + * duplex transfers such that the number of bytes received is the number + * sent and received. + */ +#define DATA_OFFSET 4 /* Start of Data for Read/Write */ +#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and + quad reads */ + +/* + * The following constants specify the page size, sector size, and number of + * pages and sectors for the FLASH. The page size specifies a max number of + * bytes that can be written to the FLASH with a single transfer. + */ +#define SECTOR_SIZE 0x1000 +#define NUM_SECTORS 0x100 + +/* + * Flash address to which data is to be written. + */ +#define TEST_ADDRESS 0x00 +#define UNIQUE_VALUE 0x05 + +/* + * The following constants specify the max amount of data and the size of the + * the buffer required to hold the data and overhead to transfer the data to + * and from the FLASH. + */ +#define MAX_DATA SECTOR_SIZE * NUM_SECTORS + +/* + * The following constant defines the slave select signal that is used to + * to select the FLASH device on the SPI bus, this signal is typically + * connected to the chip select of the device + */ +#define FLASH_SPI_SELECT 0x01 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr, + XSpiPs *SpiInstancePtr, u16 SpiIntrId); + +static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId); + +void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount); + +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount); +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command); +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command); +int WriteEnable(XIsf *InstancePtr); +int SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr, + u16 SpiDeviceId, u16 SpiIntrId); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XScuGic IntcInstance; +static XSpiPs SpiInstance; +static XIsf Isf; +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile int TransferInProgress; + +/* + * The following variable tracks any errors that occur during interrupt + * processing + */ +int ErrorCount; + +/* + * The following variables are used to read and write to the eeprom and they + * are global to avoid having large buffers on the stack + */ +u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE]; +u8 WriteBuffer[MAX_DATA + DATA_OFFSET]; +u8 IsfWriteBuffer[XISF_CMD_SEND_EXTRA_BYTES + 1]; + +/*****************************************************************************/ +/** +* +* Main function to call the SPI Flash example. +* +* @param None +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("SPI FLASH Interrupt Example Test \r\n"); + + /* + * Run the Spi Interrupt example. + */ + Status = SpiFlashIntrExample(&IntcInstance, &SpiInstance, + SPI_DEVICE_ID, SPI_INTR_ID); + if (Status != XST_SUCCESS) { + xil_printf("SPI FLASH Interrupt Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran SPI FLASH Interrupt Example Test\r\n"); + return XST_SUCCESS; +} + +/***************************************************************************** +* +* The purpose of this function is to illustrate how to use the XSpiPs +* device driver in interrupt mode. This function writes and reads data +* from a serial FLASH. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* +* This function calls other functions which contain loops that may be infinite +* if interrupts are not working such that it may not return. If the device +* slave select is not correct and the device is not responding on bus it will +* read a status of 0xFF for the status register as the bus is pulled up. +* +*****************************************************************************/ +int SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr, + u16 SpiDeviceId, u16 SpiIntrId) +{ + int Status; + u8 *BufferPtr; + u8 UniqueValue; + u32 Count; + XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */ + u32 TempAddress; + + /* + * Lookup the device configuration in the temporary CROM table. Use this + * configuration info down below when initializing this component. + */ + ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId); + if (ConfigPtr == NULL) { + return XST_DEVICE_NOT_FOUND; + } + + XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr, + ConfigPtr->BaseAddress); + + /* Initialize the XILISF Library */ + XIsf_Initialize(&Isf, SpiInstancePtr, FLASH_SPI_SELECT, + IsfWriteBuffer); + + XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE); + + /* + * Connect the Spi device to the interrupt subsystem such that + * interrupts can occur. This function is application specific + */ + Status = SpiSetupIntrSystem(IntcInstancePtr, SpiInstancePtr, + SpiIntrId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the + * interrupt context when an SPI status occurs, specify a pointer to + * the SPI driver instance as the callback reference so the handler is + * able to access the instance data + */ + XIsf_SetStatusHandler(&Isf, SpiInstancePtr, + (XSpiPs_StatusHandler) SpiHandler); + + + memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); + memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); + + /* Unprotect Sectors */ + FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG); + + FlashErase(&Isf, TEST_ADDRESS, MAX_DATA); + + /* + * Initialize the write buffer for a pattern to write to the FLASH + * and the read buffer to zero so it can be verified after the read, the + * test value that is added to the unique value allows the value to be + * changed in a debug environment to guarantee + */ + TempAddress = TEST_ADDRESS; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++, TempAddress++) { + WriteBuffer[0] = (u8)(UniqueValue); + FlashWrite(&Isf, TempAddress, 1, XISF_WRITE); + } + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read + * command + */ + FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ); + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + BufferPtr = &ReadBuffer[DATA_OFFSET]; + + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + if (BufferPtr[Count] != (u8)(UniqueValue)) { + return XST_FAILURE; + } + } + + SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the STM Serial Flash is ready to accept next command. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and + waits till the WIP bit of the status register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is in progress. + */ + while(TransferInProgress); + + /* + * Check if there are any errors in the transaction. + */ + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + * If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + + +/****************************************************************************** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts but is +* application specific. +* +* @param CallBackRef is a reference passed to the handler. +* @param StatusEvent is the status of the SPI . +* @param ByteCount is the number of bytes transferred. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/****************************************************************************** +* +* +* This function writes to the serial FLASH connected to the SPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to write data to in the FLASH. +* @param ByteCount contains the number of bytes to write. +* @param Command is the command used to write data to the flash. SPI +* device supports Byte Program command to write data to the +* flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command) +{ + XIsf_WriteParam WriteParam; + + int Status; + + WriteEnable(InstancePtr); + + WriteParam.Address = Address; + WriteParam.NumBytes = ByteCount; + WriteParam.WritePtr = WriteBuffer; + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, Command, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +/****************************************************************************** +* +* This function reads from the serial FLASH connected to the +* SPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to read data from in the FLASH. +* @param ByteCount contains the number of bytes to read. +* @param Command is the command used to read data from the flash. SPI +* device supports one of the Read, Fast Read, Dual Read and Fast +* Read commands to read data from the flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command) +{ + XIsf_ReadParam ReadParam; + int Status; + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ByteCount; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the Read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, Command, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +/****************************************************************************** +* +* +* This function erases the sectors in the serial FLASH connected to the SPI +* interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address of the first sector which needs to +* be erased. +* @param ByteCount contains the total size to be erased. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount) +{ + int Status; + int Sector; + + /* + * If the erase size is less than the total size of the flash, use + * sector erase command + */ + for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) { + + /* + * Write enable instruction has to be executed prior to + * any Write operation. + */ + WriteEnable(InstancePtr); + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Address += SECTOR_SIZE; + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function performs the write enable operation. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* +******************************************************************************/ +int WriteEnable(XIsf *InstancePtr) +{ + int Status; + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system for an Spi device. +* +* @param IntcInstancePtr is a pointer to the instance of the Intc device. +* @param SpiInstancePtr is a pointer to the instance of the Spi device. +* @param SpiIntrId is the interrupt Id for an SPI device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr, + XSpiPs *SpiInstancePtr, u16 SpiIntrId) +{ + int Status; + + XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */ + + Xil_ExceptionInit(); + + /* + * Initialize the interrupt controller driver so that it is ready to + * use. + */ + IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); + if (NULL == IntcConfig) { + return XST_FAILURE; + } + + Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, + IntcConfig->CpuBaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + IntcInstancePtr); + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + Status = XScuGic_Connect(IntcInstancePtr, SpiIntrId, + (Xil_ExceptionHandler)XSpiPs_InterruptHandler, + (void *)SpiInstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Enable the interrupt for the Spi device. + */ + XScuGic_Enable(IntcInstancePtr, SpiIntrId); + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function disables the interrupts that occur for the Spi device. +* +* @param IntcInstancePtr is the pointer to an INTC instance. +* @param SpiIntrId is the interrupt Id for an SPI device. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId) +{ + /* + * Disable the interrupt for the SPI device. + */ + XScuGic_Disable(IntcInstancePtr, SpiIntrId); + + /* + * Disconnect and disable the interrupt for the Spi device. + */ + XScuGic_Disconnect(IntcInstancePtr, SpiIntrId); +} diff --git a/lib/sw_services/xilisf/examples/xilisf_spips_sst_polled_example.c b/lib/sw_services/xilisf/examples/xilisf_spips_sst_polled_example.c new file mode 100644 index 00000000..fcbb5cd3 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_spips_sst_polled_example.c @@ -0,0 +1,480 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_spips_flash_polled_example.c +* +* This file contains a design example using the XILISF Library in +* interrupt mode with a serial FLASH device. This examples performs +* some transfers in Auto mode and Manual start mode, to illustrate the modes +* available. +* The hardware which this example runs on, must have a serial FLASH (Numonyx +* N25Q, Winbond W25Q, SST or Spansion S25FL) for it to run. This example has +* been tested with the SST Flash. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  srt 06/20/12 First release
+* 3.01  srt 03/03/13 Modified the flash write, erase and read logic.
+*		     Ensured flash blocks are unprotected befor a flash erase
+*		     or write operation. (CR 703816)
+* 3.02  srt 04/26/13 Modified Erase function to perform Write Enable operation
+*		     for each sector erase.
+*
+*
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xscugic.h" /* Interrupt controller device driver */ +#include "xil_exception.h" +#include "xil_printf.h" +#include + +/************************** Constant Definitions *****************************/ + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID + +/* + * The following constants define the offsets within a FlashBuffer data + * type for each kind of data. Note that the read data offset is not the + * same as the write data because the SPI driver is designed to allow full + * duplex transfers such that the number of bytes received is the number + * sent and received. + */ +#define DATA_OFFSET 4 /* Start of Data for Read/Write */ +#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and + quad reads */ + +/* + * The following constants specify the page size, sector size, and number of + * pages and sectors for the FLASH. The page size specifies a max number of + * bytes that can be written to the FLASH with a single transfer. + */ +#define SECTOR_SIZE 0x1000 +#define NUM_SECTORS 0x100 + +/* + * Flash address to which data is to be written. + */ +#define TEST_ADDRESS 0x00 +#define UNIQUE_VALUE 0x05 +/* + * The following constants specify the max amount of data and the size of the + * the buffer required to hold the data and overhead to transfer the data to + * and from the FLASH. + */ +#define MAX_DATA SECTOR_SIZE * NUM_SECTORS + +/* + * The following constant defines the slave select signal that is used to + * to select the FLASH device on the SPI bus, this signal is typically + * connected to the chip select of the device + */ +#define FLASH_SPI_SELECT 0x01 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount); +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command); +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command); +int WriteEnable(XIsf *InstancePtr); +int SpiFlashPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XSpiPs SpiInstance; +static XIsf Isf; + +/* + * The following variables are used to read and write to the eeprom and they + * are global to avoid having large buffers on the stack + */ +u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE]; +u8 WriteBuffer[MAX_DATA + DATA_OFFSET]; +u8 IsfWriteBuffer[XISF_CMD_SEND_EXTRA_BYTES + 1]; + +/*****************************************************************************/ +/** +* +* Main function to call the SPI Flash example. +* +* @param None +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("SPI FLASH Polled Example Test \r\n"); + + /* + * Run the Spi Interrupt example. + */ + Status = SpiFlashPolledExample(&SpiInstance,SPI_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("SPI FLASH Polled Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran SPI FLASH Polled Example Test\r\n"); + return XST_SUCCESS; +} + +/***************************************************************************** +* +* The purpose of this function is to illustrate how to use the XSpiPs +* device driver in interrupt mode. This function writes and reads data +* from a serial FLASH. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* +* This function calls other functions which contain loops that may be infinite +* if interrupts are not working such that it may not return. If the device +* slave select is not correct and the device is not responding on bus it will +* read a status of 0xFF for the status register as the bus is pulled up. +* +*****************************************************************************/ +void FlashWriteSPI(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command); +int SpiFlashPolledExample(XSpiPs *SpiInstancePtr, + u16 SpiDeviceId) +{ + u8 *BufferPtr; + u8 UniqueValue; + u32 Count; + XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */ + u32 TempAddress; + + /* + * Lookup the device configuration in the temporary CROM table. Use this + * configuration info down below when initializing this component. + */ + ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId); + if (ConfigPtr == NULL) { + return XST_DEVICE_NOT_FOUND; + } + + XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr, + ConfigPtr->BaseAddress); + + /* Initialize the XILISF Library */ + XIsf_Initialize(&Isf, SpiInstancePtr, FLASH_SPI_SELECT, + IsfWriteBuffer); + + memset(WriteBuffer, 0x00, sizeof(WriteBuffer)); + memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); + + /* Unprotect Sectors */ + FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG); + + FlashErase(&Isf, TEST_ADDRESS, MAX_DATA); + + /* + * Initialize the write buffer for a pattern to write to the FLASH + * and the read buffer to zero so it can be verified after the read, the + * test value that is added to the unique value allows the value to be + * changed in a debug environment to guarantee + */ + TempAddress = TEST_ADDRESS; + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++, TempAddress++) { + WriteBuffer[0] = (u8)(UniqueValue); + FlashWrite(&Isf, TempAddress, 1, XISF_WRITE); + } + + /* + * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read + * command + */ + FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ); + + /* + * Setup a pointer to the start of the data that was read into the read + * buffer and verify the data read is the data that was written + */ + BufferPtr = &ReadBuffer[DATA_OFFSET]; + + for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA; + Count++, UniqueValue++) { + if (BufferPtr[Count] != (u8)(UniqueValue)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Serial Flash is ready to accept next command. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and + waits till the WIP bit of the status register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + * If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/****************************************************************************** +* +* +* This function writes to the serial FLASH connected to the SPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to write data to in the FLASH. +* @param ByteCount contains the number of bytes to write. +* @param Command is the command used to write data to the flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command) +{ + XIsf_WriteParam WriteParam; + + int Status; + + WriteEnable(InstancePtr); + + WriteParam.Address = Address; + WriteParam.NumBytes = ByteCount; + WriteParam.WritePtr = WriteBuffer; + + /* + * Perform the Write operation. + */ + Status = XIsf_Write(&Isf, Command, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +/****************************************************************************** +* +* This function reads from the serial FLASH connected to the +* SPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address to read data from in the FLASH. +* @param ByteCount contains the number of bytes to read. +* @param Command is the command used to read data from the flash. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command) +{ + XIsf_ReadParam ReadParam; + int Status; + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ByteCount; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the Read operation. + */ + Status = XIsf_Read(&Isf, Command, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/****************************************************************************** +* +* +* This function erases the sectors in the serial FLASH connected to the +* SPI interface. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* @param Address contains the address of the first sector which needs to +* be erased. +* @param ByteCount contains the total size to be erased. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount) +{ + int Status; + int Sector; + + /* + * If the erase size is less than the total size of the flash, use + * sector erase command + */ + for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) { + + /* + * Write enable instruction has to be executed prior to + * any Write operation. + */ + WriteEnable(InstancePtr); + + /* + * Perform the Sector Erase operation. + */ + Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Address += SECTOR_SIZE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function performs the write enable operation. +* +* @param InstancePtr is a pointer to the XIsf component to use. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* +******************************************************************************/ +int WriteEnable(XIsf *InstancePtr) +{ + int Status; + + /* + * Perform the Write Enable operation. + */ + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_stm_quad_flash_example.c b/lib/sw_services/xilisf/examples/xilisf_stm_quad_flash_example.c new file mode 100644 index 00000000..a965153b --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_stm_quad_flash_example.c @@ -0,0 +1,972 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_stm_quad_flash_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf) for Reading/Writing to a STM (Numonyx) N25QXX Quad Serial +* Flash Device. This example shows the Erase, Dual/Quad Read and Dual/Quad +* Write features. +* +* This example +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data +* +* This example has been tested with a Numonyx Serial Flash Memory (N25Q128) on +* a Xilinx KC705 board. For further details about the Flash device refer the +* Numonyx Serial Flash Memory (N25Q128) data sheet. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.04a sdm  08/25/11 First release
+* 3.02a adk  07/08/13 Fixed the CR 721229, by setting the proper QSPI options.
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x03 /* Test Byte value written */ + +/* + * The following definitions specify the number of dummy bytes associated with + * various Read commands and the number of dummy bytes to ignore in the data + * read from the flash, through those Read commands. This is apart from the + * dummy bytes returned in response to the command and address transmitted. + */ +/* + * After transmitting Dual Read command and address on DIO0, the quad spi + * device configures DIO0 and DIO1 in input mode and receives data on both + * DIO0 and DIO1 for 8 dummy clock cycles. So we end up with 16 dummy bits + * in DRR. The same logic applies for Dual IO Read (8 dummy clock cycles = + * 16 dummy bits), Quad Read command (8 dummy clock cycles = 32 dummy bits) + * and Quad IO Read command (10 dummy clock cycles = 40 dummy bits) + */ +/* + * The number of dummy cycles is configurable in the flash device. Please refer + * to the flash datasheet for more details. + */ +#define DUAL_READ_DUMMY_BYTES 2 +#define DUAL_IO_READ_DUMMY_BYTES 2 +#define QUAD_READ_DUMMY_BYTES 4 +#define QUAD_IO_READ_DUMMY_BYTES 5 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during Read/Write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 5]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Numonyx Quad Serial Flash Read/Write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Set the QSPI options + */ + Status = XIsf_SetSpiConfiguration(&Isf, &Spi, + XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION, + XISF_SPI_PRESCALER); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * The following code Erases a Sector in the Numonyx Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_DUAL_IP_PAGE_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the flash using Dual Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = DUAL_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_DUAL_OP_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Move to the next page in the flash. + */ + Address += ISF_PAGE_SIZE; + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_DUAL_IP_EXT_PAGE_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the flash using Dual Input/Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = DUAL_IO_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_IO_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_DUAL_IO_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_IO_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Move to the next page in the flash. + */ + Address += ISF_PAGE_SIZE; + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_QUAD_IP_PAGE_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the flash using Quad Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = QUAD_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_QUAD_OP_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Move to the next page in the flash. + */ + Address += ISF_PAGE_SIZE; + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_QUAD_IP_EXT_PAGE_WRITE, + (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the flash using Quad Input/Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = QUAD_IO_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_IO_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_QUAD_IO_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_IO_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Numonyx serial Flash is ready to accept next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and +* waits till the Serial Flash is ready to accept next command. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that + * the SPI can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_stm_rdwr_polled_example.c b/lib/sw_services/xilisf/examples/xilisf_stm_rdwr_polled_example.c new file mode 100644 index 00000000..f3cb252e --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_stm_rdwr_polled_example.c @@ -0,0 +1,383 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_stm_rdwr_polled_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf) for Reading/Writing to a STM (Numonyx) M25P16 Serial Flash +* Device with the Spi driver in polled mode of operation. This example shows +* the Erase, Read and Write features. +* +* This example +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data. +* +* This example has been tested with a STM (Numonyx) M25P16 device on a Xilinx +* Spartan-3A Starter Kit board and AC701 board with a Micron flash N25Q256A +* (32MB, supporting 4 Byte addressing mode). +* +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a sdm 04/02/08 First release
+* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
+*		     to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
+* 5.2   asa 05/12/15 Added support for Micron N25Q256A flash part which
+*                    supports 4 byte addressing.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xilisf.h" /* Serial Flash Library header file */ + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x36 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XSpi Spi; + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + * For 4 byte addressing mode support, to account for the extra address bye + * the buffer size is incremented by 1. + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; + +/* + * Buffers used during Read/Write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the STM Serial Flash Read/Write polled example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the SPI driver so that the device is enabled. + */ + XSpi_Start(&Spi); + + /* + * Disable Global interrupt to use the Spi driver in polled mode + * operation. + */ + XSpi_IntrGlobalDisable(&Spi); + + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * Check is the flash part is micron in which case, switch to 4 byte + * addressing mode. + */ + if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) { + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XIsf_MicronFlashEnter4BAddMode(&Isf); + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. For Micron flash + * which supports 4 Byte mode, comparison should take care of the extra + * address byte. + */ + if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) { + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + } else { + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + } + + /* + * For micron flash part supporting 4 byte ddressing mode, exit from + * 4 Byte mode. + */ + if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) { + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XIsf_MicronFlashExit4BAddMode(&Isf); + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the STM serial Flash is ready to accept next command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and +* waits till the Serial Flash is ready to accept next command. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_stm_read_write_example.c b/lib/sw_services/xilisf/examples/xilisf_stm_read_write_example.c new file mode 100644 index 00000000..84d8e0ba --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_stm_read_write_example.c @@ -0,0 +1,585 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_stm_read_write_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf) for Reading/Writing to a STM (Numonyx) M25P16 Serial Flash +* Device. This example shows the Erase, Read and Write features. +* +* This example +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data +* +* This example has been tested with a STM (Numonyx) M25P16 device on Xilinx +* Spartan-3A Starter Kit board. +* +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  03/17/08 First release
+* 2.00a ktn  11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 5.2   asa  05/12/15 Added support for Micron N25Q256A flash.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x05 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; + +/* + * Buffers used during Read/Write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the STM Serial Flash Read/Write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Check is the flash part is micron in which case, switch to 4 byte + * addressing mode. + */ + if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) { + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + TransferInProgress = TRUE; + XIsf_MicronFlashEnter4BAddMode(&Isf); + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) { + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + } else { + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + } + + if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) { + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + TransferInProgress = TRUE; + XIsf_MicronFlashExit4BAddMode(&Isf); + + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the STM serial Flash is ready to accept next command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and +* waits till the Serial Flash is ready to accept next command. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that + * the SPI can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_stm_spr_example.c b/lib/sw_services/xilisf/examples/xilisf_stm_spr_example.c new file mode 100644 index 00000000..a14624af --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_stm_spr_example.c @@ -0,0 +1,754 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_stm_spr_example.c +* +* This file contains a design example using the Xilinx In-system and Serial +* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector +* Protection, Read and Write features. + +* This example +* - Erases a Sector +* - Writes to a Page within the erased Sector +* - Enables the Sector Protection so that all the sectors are Write protected +* - Erases a Page (This should not happen as the Sectors are Write protected +* - Reads back the Page that is written and compares the data. +* +* This example has been tested with a STM (Numonyx) Serial Flash Memory +* (M25P16) on a Xilinx Spartan-3A Starter Kit board. For further details about +* the Flash device refer to the STM (Numonyx) Serial Flash Memory (M25P16) +* data sheet. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a sdm  03/17/08 First release
+* 2.00a ktn  11/22/09 Updated to use HAL processor APIs.
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include "xspi.h" /* SPI device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Serial Flash on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the Serial Flash. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x15 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; + +/* + * The following variable tracks any errors that occur during interrupt + * processing. + */ +static int ErrorCount; + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; +u8 WriteBuffer[ISF_PAGE_SIZE]; + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the STM Serial Flash SPR example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data that needs to be written + * to the Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the sector protection register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Set all the block protection bits in the sector protection register + * value read above and write it back to the sector protection register + * to disable protection for all sectors. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] | + (XISF_SR_BLOCK_PROTECT_MASK); + + /* + * Enable the sector protection. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. This should not work as sector + * protection is enabled for all the sectors. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the sector protection register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Clear all the block protection bits in the sector protection register + * value read above and write it back to the sector protection register + * to disable protection for all sectors. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & + ~(XISF_SR_BLOCK_PROTECT_MASK); + + /* + * Disable the sector protection. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the Read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the STM Serial Flash is ready to accept next command. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and + waits till the WIP bit of the status register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is in progress. + */ + while(TransferInProgress); + + /* + * Check if there are any errors in the transaction. + */ + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + * If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specific real mode so that + * the SPI can cause interrupts thru the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + + /* + * Initialize the exception table + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_winbond_quad_flash_example.c b/lib/sw_services/xilisf/examples/xilisf_winbond_quad_flash_example.c new file mode 100644 index 00000000..a4bad9e6 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_winbond_quad_flash_example.c @@ -0,0 +1,849 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_winbond_quad_flash_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf) for Reading/Writing to a Winbond W25QXX Quad Serial Flash +* Device. This example shows the Erase, Dual/Quad Read and Quad Write +* features. +* +* This example +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data +* +* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on +* a Xilinx SP605 board. For further details about the Flash device refer the +* Winbond Serial Flash Memory (W25Q64) data sheet. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.04a sdm  08/25/11 First release
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x03 /* Test Byte value written */ + +/* + * The following definitions specify the number of dummy bytes to ignore in the + * data read from the flash, through various Read commands. This is apart from + * the dummy bytes returned in reponse to the command and address transmitted. + */ +/* + * After transmitting Dual Read command and address on DIO0, the quad spi device + * configures DIO0 and DIO1 in input mode and receives data on both DIO0 and + * DIO1 for 8 dummy clock cycles. So we end up with 16 dummy bits in DRR. The + * same logic applies Quad read command, so we end up with 4 dummy bytes in that + * case. + */ +/* + * Please refer to the flash datasheet for more details about the number of dummy + * cycles associated with each command. + */ +#define DUAL_READ_DUMMY_BYTES 2 +#define QUAD_READ_DUMMY_BYTES 4 + +#define DUAL_IO_READ_DUMMY_BYTES 1 +#define QUAD_IO_READ_DUMMY_BYTES 3 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +static int SpiFlashQuadEnable(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during Read/Write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 4]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Winbond Quad Serial Flash Read/Write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * The following code Erases a Sector in the Winbond Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the Quad Enable (QE) bit in the flash device, so that Quad + * operations can be perfomed on the flash. + */ + Status = SpiFlashQuadEnable(); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_QUAD_IP_PAGE_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the flash using Dual Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = DUAL_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_DUAL_OP_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + /* + * Enable High Performance Mode so that data can be read from the flash + * using DIO and QIO read commands. + */ + TransferInProgress = TRUE; + Status = XIsf_Ioctl(&Isf, XISF_IOCTL_ENABLE_HI_PERF_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the flash using Dual Input/Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = DUAL_IO_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_IO_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_DUAL_IO_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + DUAL_IO_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + /* + * Read from the flash using Quad Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = QUAD_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_QUAD_OP_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + /* + * Read from the flash using Quad Input/Output Fast Read command. + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + * - Number of dummy bytes for the read command. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + ReadParam.NumDummyBytes = QUAD_IO_READ_DUMMY_BYTES; + + /* + * Clear the read Buffer. + */ + for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_IO_READ_DUMMY_BYTES; Index++) { + ReadBuffer[Index] = 0x0; + } + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_QUAD_IO_FAST_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES + + QUAD_IO_READ_DUMMY_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Winbond serial Flash is ready to accept next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and +* waits till the Serial Flash is ready to accept next command. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function sets the QuadEnable bit in Winbond flash. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int SpiFlashQuadEnable(void) +{ + int Status; + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Prepare the WriteBuffer. + */ + WriteBuffer[BYTE1] = 0x00; + WriteBuffer[BYTE2] = 0x02; /* QE = 1 */ + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE_STATUS_REG2, (void*) WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that + * the SPI can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_winbond_rdwr_polled_example.c b/lib/sw_services/xilisf/examples/xilisf_winbond_rdwr_polled_example.c new file mode 100644 index 00000000..6448f8e0 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_winbond_rdwr_polled_example.c @@ -0,0 +1,355 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_winbond_rdwr_polled_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf) for Reading/Writing to a Winbond W25QXX/W25XX Serial Flash +* Device with the Spi driver in polled mode of operation. This example shows +* the Erase, Read and Write features. +* +* This example +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data +* +* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on +* a Xilinx SP605 board. For further details about the Flash device refer the +* Winbond Serial Flash Memory (W25Q64) data sheet. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 2.01a sdm 03/17/10 First release
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xilisf.h" /* Serial Flash Library header file */ + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x36 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XSpi Spi; + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during Read/Write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Winbond Serial Flash Read/Write polled example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the SPI driver so that the device is enabled. + */ + XSpi_Start(&Spi); + + /* + * Disable Global interrupt to use the Spi driver in polled mode + * operation. + */ + XSpi_IntrGlobalDisable(&Spi); + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * The following code Erases a Sector in the Winbond Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the read operation. + */ + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Winbond serial Flash is ready to accept next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and +* waits till the Serial Flash is ready to accept next command. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_winbond_read_write_example.c b/lib/sw_services/xilisf/examples/xilisf_winbond_read_write_example.c new file mode 100644 index 00000000..88c3f389 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_winbond_read_write_example.c @@ -0,0 +1,555 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_winbond_read_write_example.c +* +* This file contains a design example using the In-system and Serial Flash +* Library (XilIsf) for Reading/Writing to a Winbond W25QXX/W25XX Serial Flash +* Device. This example shows the Erase, Read and Write features. +* +* This example +* - Erases a Sector +* - Writes to a Page within the Erased Sector +* - Reads back the Page that is written and compares the data +* +* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on +* a Xilinx SP605 board. For further details about the Flash device refer the +* Winbond Serial Flash Memory (W25Q64) data sheet. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.01a sdm  03/17/10 First release
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Flash device on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the flash device. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x05 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; /* State of Spi Transfer */ +static int ErrorCount; /* Errors occurred during Spi transfers */ + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during Read/Write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */ +u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Winbond Serial Flash Read/Write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * The following code Erases a Sector in the Winbond Serial Flash. + */ + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Winbond serial Flash is ready to accept next +* command. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and +* waits till the Serial Flash is ready to accept next command. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check for errors. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the Serial Flash is ready to accept the next + * command. If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specify real mode so that + * the SPI can cause interrupts through the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/examples/xilisf_winbond_spr_example.c b/lib/sw_services/xilisf/examples/xilisf_winbond_spr_example.c new file mode 100644 index 00000000..54617004 --- /dev/null +++ b/lib/sw_services/xilisf/examples/xilisf_winbond_spr_example.c @@ -0,0 +1,754 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************** +* +* @file xilisf_winbond_spr_example.c +* +* This file contains a design example using the Xilinx In-system and Serial +* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector +* Protection, Read and Write features on a Winbond W25QXX/W25XX Serial Flash +* Device. + +* This example +* - Erases a Sector +* - Writes to a Page within the erased Sector +* - Enables the Sector Protection so that all the sectors are Write protected +* - Erases a Page (This should not happen as the Sectors are Write protected +* - Reads back the Page that is written and compares the data +* +* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on +* a Xilinx SP605 board. For further details about the Flash device refer the +* Winbond Serial Flash Memory (W25Q64) data sheet. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 2.01a sdm  03/17/10 First release
+* 5.0   sb   08/05/14 Registering to Xilisf Interrupt handler
+*		      instead of driver handler.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* EDK generated parameters */ +#include "xintc.h" /* Interrupt controller device driver */ +#include "xspi.h" /* SPI device driver */ +#include /* Serial Flash Library header file */ +#include "xil_exception.h" + +/************************** Constant Definitions *****************************/ + + +/* + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID + +/* + * The following constant defines the slave select signal that is used to + * to select the Serial Flash on the SPI bus, this signal is typically + * connected to the chip select of the device. + */ +#define ISF_SPI_SELECT 0x01 + +/* + * Number of bytes per page in the Serial Flash. + */ +#define ISF_PAGE_SIZE 256 + +/* + * Address of the page to perform Erase, Write and Read operations. + */ +#define ISF_TEST_ADDRESS 0x010000; +#define ISF_TEST_BYTE 0x15 /* Test Byte offset value written */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int IsfWaitForFlashNotBusy(void); +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount); +static int SetupInterruptSystem(XSpi *SpiPtr); + +/************************** Variable Definitions *****************************/ + +/* + * The instances to support the device drivers are global such that they + * are initialized to zero each time the program runs. They could be local + * but should at least be static so they are zeroed. + */ +static XIsf Isf; +static XIntc InterruptController; +static XSpi Spi; + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile static int TransferInProgress; + +/* + * The following variable tracks any errors that occur during interrupt + * processing. + */ +static int ErrorCount; + +/* + * The user needs to allocate a buffer to be used by the In-system and Serial + * Flash Library to perform any read/write operations on the Serial Flash + * device. + * User applications must pass the address of this memory to the Library in + * Serial Flash Initialization function, for the Library to work. + * For Write operations: + * - The size of this buffer should be equal to the Number of bytes to be + * written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES. + * - The size of this buffer should be large enough for usage across all the + * applications that use a common instance of the Serial Flash. + * - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written + * to the Serial Flash, through a single Write operation. + * The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the + * application only reads from the Serial Flash (no write operations). + */ +u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; +u8 WriteBuffer[ISF_PAGE_SIZE]; + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Winbond Serial Flash SPR example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int main() +{ + int Status; + u32 Index; + u32 Address; + XIsf_WriteParam WriteParam; + XIsf_ReadParam ReadParam; + + + /* + * Initialize the SPI driver so that it's ready to use, + * specify the device ID that is generated in xparameters.h. + */ + Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the SPI driver to the interrupt subsystem such that + * interrupts can occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Spi); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handler for the SPI that will be called from the interrupt + * context when an SPI status occurs, specify a pointer to the SPI + * driver instance as the callback reference so the handler is able to + * access the instance data. + */ + XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler); + + /* + * Start the SPI driver so that interrupts and the device are enabled. + */ + XSpi_Start(&Spi); + + /* + * Initialize the Serial Flash Library. + */ + Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set The transfer Mode to Interrupt + */ + XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE); + + /* + * Specify the address in the Serial Flash for the Erase/Write/Read + * operations. + */ + Address = ISF_TEST_ADDRESS; + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address within the Serial Flash where the data is to be written. + * - Number of bytes to be written to the Serial Flash. + * - Write Buffer which contains the data to be written to the Serial + * Flash. + */ + WriteParam.Address = Address; + WriteParam.NumBytes = ISF_PAGE_SIZE; + WriteParam.WritePtr = WriteBuffer; + + /* + * Prepare the write buffer. Fill in the data that needs to be written + * to the Serial Flash. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE; + } + + /* + * Perform the Write operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the sector protection register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Set all the block protection bits in the sector protection register + * value read above and write it back to the sector protection register + * to disable protection for all sectors. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] | + (XISF_SR_BLOCK_PROTECT_MASK); + + /* + * Enable the sector protection. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Write Enable operation. + */ + TransferInProgress = TRUE; + Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Sector Erase operation. This should not work as sector + * protection is enabled for all the sectors. + */ + TransferInProgress = TRUE; + Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read the sector protection register. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Clear all the block protection bits in the sector protection register + * value read above and write it back to the sector protection register + * to disable protection for all sectors. + */ + WriteBuffer[BYTE1] = ReadBuffer[BYTE2] & + ~(XISF_SR_BLOCK_PROTECT_MASK); + + /* + * Disable the sector protection. + */ + TransferInProgress = TRUE; + Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Wait till the Flash is not Busy. + */ + Status = IsfWaitForFlashNotBusy(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the + * - Address in the Serial Flash where the data is to be read from. + * - Number of bytes to be read from the Serial Flash. + * - Read Buffer to which the data is to be read. + */ + ReadParam.Address = Address; + ReadParam.NumBytes = ISF_PAGE_SIZE; + ReadParam.ReadPtr = ReadBuffer; + + /* + * Perform the Read operation. + */ + TransferInProgress = TRUE; + Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is complete and check if there are any errors + * in the transaction. + */ + while(TransferInProgress); + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data written. + */ + for(Index = 0; Index < ISF_PAGE_SIZE; Index++) { + if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != + (u8)(Index + ISF_TEST_BYTE)) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function waits till the Winbond Serial Flash is ready to accept the next +* command. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function reads the status register of the Serial Flash and + waits till the WIP bit of the status register becomes 0. +* +******************************************************************************/ +int IsfWaitForFlashNotBusy(void) +{ + int Status; + u8 StatusReg; + + while(1) { + + /* + * Get the Status Register. + */ + TransferInProgress = TRUE; + Status = XIsf_GetStatus(&Isf, ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait till the Transfer is in progress. + */ + while(TransferInProgress); + + /* + * Check if there are any errors in the transaction. + */ + if(ErrorCount != 0) { + return XST_FAILURE; + } + + /* + * Check if the flash is ready to accept the next command. + * If so break. + */ + StatusReg = ReadBuffer[BYTE2]; + if((StatusReg & XISF_SR_IS_READY_MASK) == 0) { + break; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing for the SPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of SPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle SPI interrupts and +* is application specific. +* +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount) +{ + /* + * Indicate the transfer on the SPI bus is no longer in progress + * regardless of the status event. + */ + TransferInProgress = FALSE; + + /* + * If the event was not transfer done, then track it as an error. + */ + if (StatusEvent != XST_SPI_TRANSFER_DONE) { + ErrorCount++; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the Spi device. This function is application specific since the actual +* system may or may not have an interrupt controller. The Spi device could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param SpiPtr is a pointer to the instance of the Spi device. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +static int SetupInterruptSystem(XSpi *SpiPtr) +{ + + int Status; + + /* + * Initialize the interrupt controller driver so that + * it's ready to use, specify the device ID that is generated in + * xparameters.h. + */ + Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect a device driver handler that will be called when an interrupt + * for the device occurs, the device driver handler performs the + * specific interrupt processing for the device. + */ + Status = XIntc_Connect(&InterruptController, + SPI_INTR_ID, + (XInterruptHandler)XSpi_InterruptHandler, + (void *)SpiPtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Start the interrupt controller such that interrupts are enabled for + * all devices that cause interrupts, specific real mode so that + * the SPI can cause interrupts thru the interrupt controller. + */ + Status = XIntc_Start(&InterruptController, XIN_REAL_MODE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Enable the interrupt for the SPI. + */ + XIntc_Enable(&InterruptController, SPI_INTR_ID); + + + /* + * Initialize the exception table. + */ + Xil_ExceptionInit(); + + /* + * Register the interrupt controller handler with the exception table. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + &InterruptController); + + /* + * Enable non-critical exceptions. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilisf/src/Makefile b/lib/sw_services/xilisf/src/Makefile new file mode 100644 index 00000000..373cce17 --- /dev/null +++ b/lib/sw_services/xilisf/src/Makefile @@ -0,0 +1,89 @@ +############################################################################### +# +# Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### + +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} +ISF_DIR = . + +LIB_SRCS = $(ISF_DIR)/xilisf.c \ + $(ISF_DIR)/xilisf_read.c \ + $(ISF_DIR)/xilisf_erase.c \ + $(ISF_DIR)/xilisf_write.c \ + $(ISF_DIR)/xilisf_spr.c + +# create ISF_SRCS based on configured options + +ISF_SRCS = $(LIB_SRCS) + +ISF_OBJS = $(ISF_SRCS:%.c=%.o) + + +EXPORT_INCLUDE_FILES = $(ISF_DIR)/include/xilisf.h \ + $(ISF_DIR)/include/xilisf_atmel.h \ + $(ISF_DIR)/include/xilisf_intelstm.h + + +libs: libxilisf.a + cp libxilisf.a $(RELEASEDIR) + make clean + +include: + @for i in $(EXPORT_INCLUDE_FILES); do \ + echo ${CP} -r $$i ${INCLUDEDIR}; \ + ${CP} -r $$i ${INCLUDEDIR}; \ + done + +clean: + rm -rf obj/*.o + rmdir obj + rm libxilisf.a + + +libxilisf.a: obj_dir print_msg_isf_base $(ISF_OBJS) + @echo "Creating archive $@" + $(ARCHIVER) rc $@ obj/*.o + +obj_dir: + mkdir obj + +print_msg_isf_base: + @echo "Compiling XilIsf Library" + +.c.o: + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) -c $< -o obj/$(@F) diff --git a/lib/sw_services/xilisf/src/include/xilisf.h b/lib/sw_services/xilisf/src/include/xilisf.h new file mode 100644 index 00000000..0a6d4e58 --- /dev/null +++ b/lib/sw_services/xilisf/src/include/xilisf.h @@ -0,0 +1,1045 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf.h +* +* The Xilinx In-system and Serial Flash (XilIsf) Library supports the Xilinx +* In-system Flash and, external Serial Flash Memories from Atmel (AT45XXXD), +* Intel (S33), ST Microelectronics (STM) (M25PXX), Winbond (W25QXX/W25XX), +* Numonyx (N25QXX) devices. Intel (S33) and STM (M25PXX) Serial Flash devices +* are now a part of Serial Flash devices provided by Numonyx. +* +* This library also supports the Spansion (S25FLXX) devices, but this family +* hasn't been tested. The support for this family of devices is limited to the +* common commands supported by the other flash families +* +* The following instructions are not supported in WinBond (W25QXX/W25XX) - +* Block Erase 32KB, Erase Suspend/Resume, Mode Bit Reset, Read Unique ID, +* and Read Manufacturer/Device ID. +* +* The following instructions are not supported in Numonyx (N25QXX)- Erase +* Suspend/Resume, Read/Write Volatile/Non-volatile configuration register. +* +* Library Description +* +* The library enables higher layer software (e.g. an application) to +* communicate with the Serial Flash. +* +* The library allows the user to Write, Read and Erase the Serial Flash. +* The user can also protect the data stored in Serial Flash from unwarranted +* modification by enabling the Sector Protection feature. User can also perform +* different Control operations on Intel, STM (Numonyx), Winbond and Spansion +* Serial Flash devices. +* +* The library supports interrupt driven mode and polled mode based on the +* mode in which the Spi driver is configured by the user. +* +* - Polled Mode of operation: All the APIs are blocking in this mode. +* - Interrupt mode of operation: It is the application's responsibility to +* acknowledge the associated Interrupt Controller's interrupts. +* The transfer is initiated and the control is given back to the user +* application. The user application has to keep track of whether the initiated +* operation is completed successfully. +* +* This library can support multiple instances of Serial Flash at a time, +* provided they are of the same device family (either Atmel, Intel, STM or +* Spansion) as the device family is selected at compile time. +* +* Device Operation +* +* The Serial Flash operates as a slave device on the SPI bus, with Xilinx SPI +* core operating as the Master. The library uses XSpi driver for communicating +* with the Serial Flash. +* +* Device Geometry +* +* - Atmel (AT45XXXD)/Xilinx ISF: +* The Atmel Serial Flash is divided into Sectors. Each Sector consists of +* multiple Blocks. Each Block contains multiple Pages. Each Page contains +* multiple Bytes. The Number of Sectors, Blocks Per Sector, Pages Per Block and +* Bytes Per Page vary for different devices within this family. +* There are two addressing modes supported by the Atmel Serial Flash: +* - Default-Addressing Mode. +* - Power-Of-2 Addressing mode. +* +* In Default Addressing mode the Atmel Serial Flash contains approximately 3% +* more Addressing memory than the Power-Of-2 addressing mode. The addressing +* mode of the Atmel Serial Flash can be known by reading the Device Status +* Register The ISF in the Xilinx devices is in Default-Addressing mode by +* default. +* +* The following Atmel flash memories are supported by this library. +* AT45DB011D AT45DB021D AT45DB041D +* AT45DB081D AT45DB161D AT45DB321D +* AT45DB642D +* +* - Intel (Numonyx) (S33) and STM (Numonyx)(M25PXX): +* The Intel and STM Serial Flash is divided into Sectors. Each Sector consists +* of multiple pages. Each Page contains 256 Bytes. The Number of Sectors +* and Pages Per Sectors vary for different devices within this family. +* +* The following Intel and STM flash memories are supported by this library. +* S3316MBIT S3332MBIT S3364MBIT +* +* M25P05_A M25P10_A M25P20 +* M25P40 M25P80 M25P16 +* M25P32 M25P64 M25P128 +* +* - Winbond W25QXX/W25XX: +* The Winbond W25QXX/W25XX Serial Flash is divided into Blocks of 64 KB and +* the blocks are divided into sectors. Each Sector consists of multiple pages. +* Each Page contains 256 Bytes. The Number of Blocks and Sectors vary for +* different devices within this family. +* The following instructions are not supported - Block Erase 32KB, Erase +* Suspend/Resume, Mode Bit Reset, Read Unique ID, and Read Manufacturer/Device +* ID. +* +* The following Winbond flash memories are supported by this library. +* W25Q80 W25Q16 W25Q32 +* W25Q64 W25Q128 W25X10 +* W25X20 W25X40 W25X80 +* W25X16 W25X32 W25X64 +* +* - Numonyx N25QXX +* The Numonyx N25QXX Serial Flash is divided into sectors of 64 KB and +* the sectors are divided into sub-sectors. Each Sector consists of multiple +* pages. Each Page contains 256 Bytes. The Number of Blocks vary for different +* devices within this family. +* The following instructions are not supported - Erase Suspend/Resume, +* Read/Write Volatile/Non-volatile configuration register. +* +* The following Numonyx flash memories are supported by this library. +* N25Q32 N25Q64 N25Q128 N25Q256A +* +* - Spansion S25FL +* The Spansion S25FL Serial Flash is divided into sectors of 64 KB and +* in devices like S25FL128/129, the sectors are divided into sub-sectors. +* Each Sector consists of multiple pages. Each Page contains 256 Bytes. The +* Number of Blocks vary for different devices within this family. +* +* The following Spansion flash memories are supported by this library. +* S25FL004 S25FL008 S25FL016 +* S25FL032 S25FL064 S25FL128/129 +* +* - Silicon Storage Technology (SST) SST25WF080 +* The SST25WF080 Serial Flash is divided into sectors of 4KB. This flash +* doesn't support Page Write commands. Supports only Byte-Write Command. +* +* Support for new parts can be easily added, when they are available from +* vendors. +* +* Library Initialization +* +* The function call XIsf_Initialize() should be called by the application +* before using any other function in the library. This function will fetch the +* Manufacturer code and Device code and determine the geometry of the Serial +* Flash used. +* +* Write Operations +* +* The XIsf_Write() API is used to write data to the Serial Flash. A maximum +* of a Page of data can be written using this API. Once the user initiates a +* write operation, the Serial Flash takes time to complete the write operation +* internally. The user has to read the Status Register (XIsf_GetStatus) to +* know if the Serial Flash is still busy with a previously initiated operation +* before initiating a new one. +* +* Using the XIsf_Write() API the user can perform several different types of +* write operations as mentioned below: +* +* - Normal Write: +* Write data to the specified locations in the Serial Flash. +* This operation is supported in Atmel, Intel, STM, Winbond and Spansion +* Serial Flash. +* +* - Dual Input Fast Program: +* This operation is similar to the Normal Write operation, except that +* the data is transmitted on two lines (DQ0 and DQ1) instead of one. +* This operation is supported in Numonyx (N25QXX) Quad Serial Flash. +* +* - Dual Input Extended Fast Program: +* This operation is similar to the Dual Input Fast Program, except that +* the address is transmitted on two lines (DQ0 and DQ1) instead of one. +* This operation is supported in Numonyx (N25QXX) Quad Serial Flash. +* +* - Quad Input Fast Program: +* This operation is similar to the Dual Input Fast Program, except that +* the data is transmitted on four lines (DQ0 - DQ3) instead of two. +* This operation is supported in Numonyx (N25QXX), Winbond (W25QXX) and +* Spansion (S25FL129) Quad Serial Flash. +* +* - Quad Input Extended Fast Program: +* This operation is similar to the Quad Input Fast Program, except that +* the address is transmitted on four lines (DQ0 - DQ3) instead of one. +* This operation is supported in Numonyx (N25QXX) Quad Serial Flash. +* +* - Auto Page Write: +* Auto rewrite the contents of the page. +* This operation is supported only for Atmel Serial Flash. +* +* - Buffer Write: +* Write data to the internal SRAM buffer of the Serial Flash. +* This operation is supported only for Atmel Serial Flash. +* +* - Buffer To Memory Write With Erase: +* Write data from the specified SRAM buffer to a page in the Serial Flash +* after erasing the page. +* This operation is supported only for Atmel Serial Flash. +* +* - Buffer To Memory Write Without Erase: +* Write data from the specified SRAM buffer to a Page in the Serial Flash +* without erasing the page. +* This operation is supported only for Atmel Serial Flash. +* +* - Write Status Register: +* Write to the Status Register of the Serial Flash. +* This operation is supported only for Intel, STM, Winbond and Spansion +* Serial Flash. +* +* - Write 2 byte Status Register: +* Write to the 16-bit Status Register of the Serial Flash. +* This operation is supported only for Winbond Serial Flash. +* +* - One Time Programmable Area Write: +* Write one byte of data in to One Time Programmable area. +* This operation is supported only for Intel Serial Flash. +* +* For Intel, STM (Numonyx), Winbond and Spansion Serial Flash devices, the user +* application must call the XIsf_WriteEnable() API by passing XISF_WRITE_ENABLE +* as an argument before calling the Isf_Write() API. +* +* +* Read Operations +* +* The XIsf_Read() API can be used to read a minimum of one byte and a maximum of +* an entire array of the Serial Flash depending on the type of read operation. +* +* Using the XIsf_Read() API the user can perform several different types of read +* operations as mentioned below: +* +* - Normal Read: +* Read data from the specified locations in the Serial Flash . +* This operation is supported for Atmel, Intel, STM, Winbond and Spansion +* Serial Flash. +* +* - Fast Read: +* Read a large block of contiguous data from the specified locations of +* the Serial Flash at a higher speed than the Normal Read. +* This operation is supported for Atmel, Intel, STM, Winbond and Spansion +* Serial Flash. +* +* - Dual Output Fast Read: +* This operation is similar to the Fast Read, except that the data is +* transmitted on two lines (DQ0 and DQ1) instead of one. +* This operation is supported in Numonyx (N25QXX), Winbond (W25QXX) and +* Spansion (S25FL129) Quad Serial Flash. +* +* - Dual Input/Output Fast Read: +* This operation is similar to the Dual Output Fast Read, except that +* the address is transmitted on two lines (DQ0 and DQ1) instead of one. +* This operation is supported in Numonyx (N25QXX), Winbond (W25QXX) and +* Spansion (S25FL129) Quad Serial Flash. +* +* - Quad Output Fast Read: +* This operation is similar to the Dual Output Fast Read, except that +* the data is transmitted on four lines (DQ0 - DQ3) instead of two. +* This operation is supported in Numonyx (N25QXX), Winbond (W25QXX) and +* Spansion (S25FL129) Quad Serial Flash. +* +* - Quad Input/Output Fast Read: +* This operation is similar to the Quad Output Fast Program, except that +* the address is transmitted on four lines (DQ0 - DQ3) instead of one. +* This operation is supported in Numonyx (N25QXX), Winbond (W25QXX) and +* Spansion (S25FL129) Quad Serial Flash. +* +* - Memory To Buffer Transfer: +* Transfer a page of data from the Serial Flash to the specified +* internal SRAM buffer of the Serial Flash. +* This operation is supported only in Atmel Serial Flash. +* +* - Buffer Read: +* Read data from the specified SRAM internal buffer of the Serial Flash. +* This operation is supported only in Atmel Serial Flash. +* +* - Fast Buffer Read: +* Read multiple contiguous bytes from the internal SRAM page buffer of +* Serial Flash at a higher speed than normal Buffer Read. +* This operation is supported only for Atmel Serial Flash. +* +* - One Time Programmable Area Read: +* Read One Time Programmable area. +* This operation is supported only for Intel Serial Flash. +* +* Erase Operations +* +* The XIsf_Erase() API can be used to Erase the contents of the Serial Flash. +* Once the user initiates an Erase operation, the Serial Flash takes time to +* complete the Erase operation internally. The user has to read the Status +* Register to know if Serial Flash is still busy with a previously initiated +* operation before initiating a new one. +* +* Using the XIsf_Erase() API the user can perform four different types of Erase +* operations as mentioned below : +* +* - Page Erase: +* Erase one Page of the Serial Flash. +* This operation is supported only for Atmel Serial Flash. +* +* - Block Erase: +* Erase one Block of the Serial Flash. +* This operation is supported for Atmel, Intel, Winbond Serial Flash. +* +* - Sector Erase: +* Erase one Sector of the Serial Flash. +* This operation is supported for Atmel, Intel, STM, Spansion and Winbond +* Serial Flash. +* +* - Bulk Erase: +* Erase an entire Serial Flash. +* This operation is supported for Intel, STM, Winbond and Spansion Serial +* Flash. +* +* For Intel, STM, Winbond and Spansion Serial Flash the user application must +* call the XIsf_WriteEnable() API by passing XISF_WRITE_ENABLE as an argument +* before calling the XIsf_Erase() API. +* +* Sector Protection Operations +* +* The XIsf_SectorProtect() API can be used to perform Sector Protection related +* operations. The Serial Flash is divided into Sectors. Each Sector or number of +* Sectors can be protected from unwarranted writing/erasing. +* +* Using the XIsf_SectorProtect() API the user can perform five different type of +* operations as given below: +* +* - Sector Protect Register Read: +* Read Sector Protect Register/Bits in to the buffer provided by user. +* This operation is supported for Atmel, Intel, STM, Winbond and Spansion +* Serial Flash. +* +* - Sector Protect Register Write: +* Write data to the Sector Protect Register/Bits. +* This operation is supported for Atmel, Intel, STM, Winbond and Spansion +* Serial Flash. +* +* - Sector Protect Register Erase: +* Erase the Sector Protect Register. +* This operation is supported only for Atmel Serial Flash. +* +* - Sector Protect Enable: +* Enable Sector Protect mode of Serial Flash. +* This operation is supported only for Atmel Serial Flash. +* +* - Sector Protect Disable: +* Disable Sector Protect mode of Serial Flash. +* This operation is supported only for Atmel Serial Flash. +* +* For Intel, STM, Winbond and Spansion Serial Flash the user application must +* call the XIsf_WriteEnable() API by passing XISF_WRITE_ENABLE as an argument +* before calling the XIsf_SectorProtect() API for Sector Protect Register +* Write operation. +* +* Device Control Operations +* +* The XIsf_Ioctl() API can be used to perform control operations on the +* Intel, STM, Winbond and Spansion Serial Flash. +* +* Using the XIsf_Ioctl() API the user can perform several different types of +* operations as given below: +* +* - Release From Deep Power-Down Mode: +* This operation releases the Serial Flash from Deep Power-Down Mode. +* This operation is supported for Intel, STM, Winbond and Spansion Serial +* Flash. +* +* - Enter to Deep Power-Down Mode: +* This operation puts the Serial Flash in to Deep Power-Down Mode. +* In this mode all commands except the release from Deep Power-Down Mode +* command will be ignored. +* This operation is supported for Intel, STM, Winbond and Spansion Serial +* Flash. +* +* - Clear Status Register Fail Flag: +* This operation clears all the fail flags in the Status Register +* of the Serial Flash. +* This operation is only supported for Intel Serial Flash. +* +* - High Performance Mode: +* This instruction must be executed before the dual/quad I/O instructions +* in Winbond Flash. This instruction is supported only in Winbond (W25QXX) +* Serial Flash. +* +* Serial Flash Information Read +* +* XIsf_GetDeviceInfo() API is used to read the Joint Electron Device +* Engineering Council (JEDEC) compatible device information. +* This JEDEC information consists of Manufacturer ID, Vendor-Specific Device +* family identifier, Vendor-Specific device identifier for the specified family, +* number of bits stored per memory cell, product version and number of +* additional Extended Device Information bytes. +* +* Read the Spartan-3AN In-system Flash User Guide and the data sheets of +* Atmel-AT45XXXD/STM-M25PXX/Intel-S33/Winbond-W25QXX/W25XX/Spansion-S25FLXX for +* more information. +* +* XIsf_GetStatus() API is used to read the Status Register of the Serial Flash. +* Winbond devices have a Status Register 2 which can be read using the +* XIsf_GetStatusReg2() API. +* +* Write Enable/Disable Operations +* +* For Intel, STM, Winbond and Spansion Serial Flash the user application must +* enable the Write to the Serial Flash by calling XIsf_WriteEnable +* (XISF_WRITE_ENABLE) API before doing any Write operations to Serial Flash. +* Writing to the Serial Flash is disabled by calling XIsf_WriteEnable +* (XISF_WRITE_DISABLE) API. +* +* @note +* +* This library 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 or cache control must be satisfied by the +* layer above this driver. +* +* This library supports the Spansion (S25FLXX) devices, but this family hasn't +* been tested. The support for this family of devices is limited to the common +* commands supported by the other flash families. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+* 2.00a ktn	 11/27/09 Updated to use HAL processor APIs/definitions
+* 2.01a sdm	 01/04/10 Added Support for Winbond W25Q80/16/32 devices
+* 2.01a sdm	 06/17/10 Updated the Tcl to support axi_spi
+* 2.03a sdm	 04/17/10 Updated to support Winbond memory W25Q128 and added
+*			  a list of supported flash memories
+*			  Updated the Tcl to support axi_quad_spi
+* 2.04a sdm	 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
+*			  flash memories
+* 3.00a srt	 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
+*			  New API:
+*			  	XIsf_RegisterInterface()
+*				XIsf_SetSpiConfiguration()
+*				XIsf_SetOperatingMode()
+*			  Changed API:
+*			 	XIsf_Initialize()
+*				XIsf_Transfer()
+*			  Added support to SST flash.
+* 3.01a srt	 02/06/13 Updated for changes made in QSPIPS driver (CR 698107).
+*				      APIs changed:
+*					  XQspiPs_PolledTransfer()
+*					  XQspiPs_Transfer()
+*					  XQspiPs_SetSlaveSelect().
+*			  Modified the examples xilisf_spips_sst_intr_example.c
+*			  and xilisf_spips_sst_polled_example.c to correct
+*			  the flash write, erase and read logic. (CR 703816)
+* 3.02a srt	 04/25/13 - Added Bulk Erase command support for SST and
+*			    Spansion flashes (CR 703816 & 711003).
+* 			  - Modified SECTOR and BLOCK Erase commands for
+*			    SST flash and updated spips examples.
+*			    (CR 703816)
+*			  - Updated spips and qspips examples to perform
+*			    Write enable operation in each sector
+*			  - Removed compiler errors when not selecting proper
+*			    interface for Zynq. (CR 716451)
+* 5.0   sb	 08/05/14 - Updated for support for > 128 MB flash for PSQSPI
+*			    Interface.
+*			  - Added Library Handler API which will
+*			    register to driver interrupts, based upon the
+*			    interface selected.
+*			  New API:
+*				GetRealAddr()
+*				SendBankSelect()
+*				XIsf_SetStatusHandler()
+*				XIsf_IfaceHandler()
+* 5.1   sb	 12/23/14 Added check for flash interface for Winbond, Spansion
+*			  and Micron flash family for PSQSPI.
+* 5.2   asa  5/12/15 Added support for Micron N25Q256A (>16MB) flash devices.
+*               This meant adding necessary support for 4 byte addressing mode.
+*               APIs were added to enter and exit from 4 byte mode. Changes were
+*               made in read, erase and write APIs to support 4 byte mode.
+*               These were done to fix CR#858950.
+*
+* 
+* +******************************************************************************/ +#ifndef XILISF_H /* prevent circular inclusions */ +#define XILISF_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xparameters.h" + +#ifdef XPAR_XISF_INTERFACE_AXISPI +#include "xspi.h" +#elif XPAR_XISF_INTERFACE_PSSPI +#include "xspips.h" +#elif XPAR_XISF_INTERFACE_PSQSPI +#include "xqspips.h" +#endif + +/** + * The following definitions specify the type of Serial Flash family. + * Based on the Serial Flash family selected, some part of the code is included + * or excluded in the In-system and Serial Flash Library. + */ +#define ATMEL 1 /**< Atmel family device */ +#define INTEL 2 /**< Intel family device */ +#define STM 3 /**< STM family device */ +#define WINBOND 4 /**< Winbond family device */ +#define SPANSION 5 /**< Spansion family device */ +#define SST 6 /**< SST family device */ + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) +#include "xilisf_atmel.h" +#endif + +#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST)) +#include "xilisf_intelstm.h" +#endif + +/************************** Constant Definitions *****************************/ + +/** + * The following definitions specify the Manufacturer Code for the different + * families of Serial Flash supported by this library. + */ +#define XISF_MANUFACTURER_ID_ATMEL 0x1F /**< Atmel device */ +#define XISF_MANUFACTURER_ID_INTEL 0x89 /**< Intel device */ +#define XISF_MANUFACTURER_ID_STM 0x20 /**< STM device */ +#define XISF_MANUFACTURER_ID_WINBOND 0xEF /**< Winbond device */ +#define XISF_MANUFACTURER_ID_SPANSION 0x01 /**< Spansion device */ +#define XISF_MANUFACTURER_ID_SST 0xBF /**< SST device */ +#define XISF_MANUFACTURER_ID_MICRON 0x20 /**< Micron device */ + +#define XISF_SPANSION_ID_BYTE2_128 0x18 +#define XISF_SPANSION_ID_BYTE2_256 0x19 +#define XISF_SPANSION_ID_BYTE2_512 0x20 +/*Micron*/ +#define XISF_MICRON_ID_BYTE2_128 0x18 +#define XISF_MICRON_ID_BYTE2_256 0x19 +#define XISF_MICRON_ID_BYTE2_512 0x20 +#define XISF_MICRON_ID_BYTE2_1G 0x21 +/*Winbond*/ +#define XISF_WINBOND_ID_BYTE2_128 0x18 + + + +#define READ_STATUS_CMD 0x05 +#define WRITE_ENABLE_CMD 0x06 +#define READ_FLAG_STATUS_CMD 0x70 + +#define RD_ID_SIZE 4 +#define DIE_ERASE_SIZE 4 +#define DIE_ERASE_CMD 0xC4 +#define READ_ID 0x9F + +/* + * QSPI Flash Connection Mode + */ +#define XISF_QSPIPS_CONNECTION_MODE_SINGLE 0 +#define XISF_QSPIPS_CONNECTION_MODE_STACKED 1 +#define XISF_QSPIPS_CONNECTION_MODE_PARALLEL 2 + +/* + * The index for Flash config table + */ +/* Spansion*/ +#define SPANSION_INDEX_START 0 +#define FLASH_CFG_TBL_SINGLE_128_SP SPANSION_INDEX_START +#define FLASH_CFG_TBL_STACKED_128_SP (SPANSION_INDEX_START + 1) +#define FLASH_CFG_TBL_PARALLEL_128_SP (SPANSION_INDEX_START + 2) +#define FLASH_CFG_TBL_SINGLE_256_SP (SPANSION_INDEX_START + 3) +#define FLASH_CFG_TBL_STACKED_256_SP (SPANSION_INDEX_START + 4) +#define FLASH_CFG_TBL_PARALLEL_256_SP (SPANSION_INDEX_START + 5) +#define FLASH_CFG_TBL_SINGLE_512_SP (SPANSION_INDEX_START + 6) +#define FLASH_CFG_TBL_STACKED_512_SP (SPANSION_INDEX_START + 7) +#define FLASH_CFG_TBL_PARALLEL_512_SP (SPANSION_INDEX_START + 8) + +/* Micron */ +#define MICRON_INDEX_START (FLASH_CFG_TBL_PARALLEL_512_SP + 1) +#define FLASH_CFG_TBL_SINGLE_128_MC MICRON_INDEX_START +#define FLASH_CFG_TBL_STACKED_128_MC (MICRON_INDEX_START + 1) +#define FLASH_CFG_TBL_PARALLEL_128_MC (MICRON_INDEX_START + 2) +#define FLASH_CFG_TBL_SINGLE_256_MC (MICRON_INDEX_START + 3) +#define FLASH_CFG_TBL_STACKED_256_MC (MICRON_INDEX_START + 4) +#define FLASH_CFG_TBL_PARALLEL_256_MC (MICRON_INDEX_START + 5) +#define FLASH_CFG_TBL_SINGLE_512_MC (MICRON_INDEX_START + 6) +#define FLASH_CFG_TBL_STACKED_512_MC (MICRON_INDEX_START + 7) +#define FLASH_CFG_TBL_PARALLEL_512_MC (MICRON_INDEX_START + 8) +#define FLASH_CFG_TBL_SINGLE_1GB_MC (MICRON_INDEX_START + 9) +#define FLASH_CFG_TBL_STACKED_1GB_MC (MICRON_INDEX_START + 10) +#define FLASH_CFG_TBL_PARALLEL_1GB_MC (MICRON_INDEX_START + 11) + +/* Winbond */ +#define WINBOND_INDEX_START (FLASH_CFG_TBL_PARALLEL_1GB_MC + 1) +#define FLASH_CFG_TBL_SINGLE_128_WB WINBOND_INDEX_START +#define FLASH_CFG_TBL_STACKED_128_WB (WINBOND_INDEX_START + 1) +#define FLASH_CFG_TBL_PARALLEL_128_WB (WINBOND_INDEX_START + 2) + + +/* + * Interrupt or Polling mode of Operation Flags + */ +#define XISF_POLLING_MODE 0 +#define XISF_INTERRUPT_MODE 1 +/* + * SPI Options flags + */ +#ifdef XPAR_XISF_INTERFACE_AXISPI +#define XISF_SPI_OPTIONS (XSP_MASTER_OPTION | \ + XSP_MANUAL_SSELECT_OPTION | \ + XSP_CLK_PHASE_1_OPTION | \ + XSP_CLK_ACTIVE_LOW_OPTION) +#elif XPAR_XISF_INTERFACE_PSQSPI +#define XISF_SPI_OPTIONS (XQSPIPS_MANUAL_START_OPTION | \ + XQSPIPS_FORCE_SSELECT_OPTION) +#elif XPAR_XISF_INTERFACE_PSSPI +#define XISF_SPI_OPTIONS (XSPIPS_MASTER_OPTION | \ + XSPIPS_FORCE_SSELECT_OPTION) +#endif + +/* + * PS SPI/QSPI PreScaler Settings + */ +#ifdef XPAR_XISF_INTERFACE_PSQSPI +#define XISF_SPI_PRESCALER XQSPIPS_CLK_PRESCALE_4 +#elif XPAR_XISF_INTERFACE_PSSPI +#define XISF_SPI_PRESCALER XSPIPS_CLK_PRESCALE_8 +#elif XPAR_XISF_INTERFACE_AXISPI +#define XISF_SPI_PRESCALER 0 +#endif + +/** + * The following definitions determines the type of Write operation to be + * performed on the Serial Flash. + */ +typedef enum { + XISF_WRITE, /**< Normal write operation */ + XISF_AUTO_PAGE_WRITE, /**< Auto rewrite the contents + * of the page */ + XISF_BUFFER_WRITE, /**< Write data to the internal + * SRAM buffer of Flash */ + XISF_BUF_TO_PAGE_WRITE_WITH_ERASE, /**< Erase the specified Page + * then Write data to Flash + * from the internal SRAM + * buffer */ + XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE, /**< Write data to the Flash + * from the internal SRAM + * buffer */ + XISF_WRITE_STATUS_REG, /**< Write to the Status + * Register */ + XISF_OTP_WRITE, /**< Write one byte of data in + * to the One Time + * Programmable area */ + XISF_WRITE_STATUS_REG2, /**< Write to the 2 byte Status + * Register in W25QXX flash */ + +#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) + XISF_QUAD_IP_PAGE_WRITE, /**< Quad input fast page write + */ +#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) || + (XPAR_XISF_FLASH_FAMILY == STM) || + (XPAR_XISF_FLASH_FAMILY == SPANSION))*/ + +#if (XPAR_XISF_FLASH_FAMILY == STM) + XISF_DUAL_IP_PAGE_WRITE, /**< Dual input fast page write + */ + XISF_DUAL_IP_EXT_PAGE_WRITE, /**< Dual input extended fast + * page write */ + XISF_QUAD_IP_EXT_PAGE_WRITE, /**< Dual input extended fast + * page write */ +#endif /* (XPAR_XISF_FLASH_FAMILY == STM) */ +} XIsf_WriteOperation; + +/** + * The following definitions determines the type of Read operations to be + * performed on the Serial Flash. + */ +typedef enum { + XISF_READ, /**< Normal Read operation */ + XISF_FAST_READ, /**< Fast Read operation */ + XISF_PAGE_TO_BUF_TRANS, /**< Transfer data from Flash memory to + * internal SRAM buffer of Flash */ + XISF_BUFFER_READ, /**< Read data from SRAM internal buffer of + * the Flash */ + XISF_FAST_BUFFER_READ, /**< Fast SRAM buffer read operation on Flash */ + XISF_OTP_READ, /**< Read One Time Programmable area */ + +#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \ + || (XPAR_XISF_FLASH_FAMILY == SPANSION)) + XISF_DUAL_OP_FAST_READ, /**< Dual output fast read */ + XISF_DUAL_IO_FAST_READ, /**< Dual input/output fast read */ + XISF_QUAD_OP_FAST_READ, /**< Quad output fast read */ + XISF_QUAD_IO_FAST_READ, /**< Quad input/output fast read */ +#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) || + (XPAR_XISF_FLASH_FAMILY == STM)) || + (XPAR_XISF_FLASH_FAMILY == SPANSION)*/ +} XIsf_ReadOperation; + +/** + * The following definitions determines the type of Erase operation to be + * performed on the Serial Flash. + */ +typedef enum { + XISF_PAGE_ERASE, /**< Page Erase operation */ + XISF_BLOCK_ERASE, /**< Block Erase operation */ + XISF_SECTOR_ERASE, /**< Sector Erase operation */ + XISF_BULK_ERASE /**< Erase an entire Flash */ +} XIsf_EraseOperation; + +/** + * The following definitions determines the type of Sector protection + * operations to be performed on the Serial Flash. + */ +typedef enum { + XISF_SPR_READ, /**< Sector protect register read */ + XISF_SPR_WRITE, /**< Sector protect register write */ + XISF_SPR_ERASE, /**< Sector protect register erase */ + XISF_SP_ENABLE, /**< Sector protect enable */ + XISF_SP_DISABLE /**< Sector protect disable */ +} XIsf_SpOperation; + +/** + * The following definitions determines the type of control operations to be + * performed on the Serial Flash. + */ +typedef enum { + XISF_IOCTL_RELEASE_DPD, /**< Release from Deep Power-down */ + XISF_IOCTL_ENTER_DPD, /**< Enter in to Deep Power-down mode */ + XISF_IOCTL_CLEAR_SR_FAIL_FLAGS, /**< Clear Status Register Fail Flags */ + XISF_IOCTL_ENABLE_HI_PERF_MODE /**< Enable high performance mode + * (availabe in Winbond quad flash + * (W25Q)) */ +} XIsf_IoctlOperation; + +/**************************** Type Definitions *******************************/ + +#ifdef XPAR_XISF_INTERFACE_AXISPI +typedef XSpi XIsf_Iface; +#elif XPAR_XISF_INTERFACE_PSSPI +typedef XSpiPs XIsf_Iface; +#elif XPAR_XISF_INTERFACE_PSQSPI +typedef XQspiPs XIsf_Iface; +#endif +typedef void (*XIsf_StatusHandler) (void *CallBackRef, u32 StatusEvent, + unsigned int ByteCount); + +/** + * The following definition specifies the instance structure of the Serial + * Flash. + */ +typedef struct { + u8 IsReady; /**< Is Device is ready for operation */ + + u16 BytesPerPage; /**< Number of Bytes per Page */ + u16 PagesPerBlock; /**< This is Number of Pages per block, + for Atmel and it is Number of + Pages per sector for + Intel/STM/Winbond/Spansion */ + u16 BlocksPerSector; /**< Number of Blocks per Sector, this is valid + * for ATMEL devices */ + u16 NumOfSectors; /**< Number of Sectors in Serial Flash */ + u8 AddrMode; /**< Type of addressing in Atmel Serial Flash + * 0 - Default/Normal Addressing Mode + * 1 - Power-Of-2 Addressing Mode */ + u16 DeviceCode; /**< The Serial Flash Device Code */ +#ifdef XPAR_XISF_INTERFACE_PSQSPI + u8 DeviceIDMemSize; /**< Byte of device ID indicating the memory + * size */ + u8 NumDie; /**< No. of die forming a single flash */ + u32 SectorSize; /**< Size of the Sector */ + u32 NumSectors; /**< No. of sectors */ +#endif + u32 ManufacturerID; /**< Serial Flash Manufacturer ID */ + XIsf_Iface *SpiInstPtr; /**< SPI Device Instance pointer */ + u32 SpiSlaveSelect; /**< SPI Slave select for the Serial Flash */ + u8 *WriteBufPtr; /**< Pointer to Write Buffer */ + + u16 ByteMask; /**< Mask used for Address translation in Atmel + * devices */ + u8 RegDone; /**< Registration Done flag */ + u8 IntrMode; /**< Operating Mode flag Interrupt/Polling */ + u8 FourByteAddrMode; /**< In four byte address mode flag */ + int (*XIsf_Iface_SetOptions) + (XIsf_Iface *InstancePtr, u32 Options); +#ifndef XPAR_XISF_INTERFACE_PSQSPI + int (*XIsf_Iface_SetSlaveSelect) + (XIsf_Iface *InstancePtr, u8 SlaveMask); +#else + int (*XIsf_Iface_SetSlaveSelect) + (XIsf_Iface *InstancePtr); +#endif + int (*XIsf_Iface_Start) + (XIsf_Iface *InstancePtr); + int (*XIsf_Iface_Transfer) + (XIsf_Iface *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, unsigned int ByteCount); + int (*XIsf_Iface_PolledTransfer) + (XIsf_Iface *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, unsigned ByteCount); + int (*XIsf_Iface_SetClkPrescaler) + (XIsf_Iface *InstancePtr, u8 PreScaler); + XIsf_StatusHandler StatusHandler; +} XIsf; + +/** + * The following structure definition specifies the operational parameters to be + * passed to the XIsf_Write API while performing Normal write (XISF_WRITE) and + * OTP write (XISF_OTP_WRITE) operations. + */ +typedef struct { + u32 Address; /**< Address in the Serial Flash */ + u8 *WritePtr; /**< Pointer to the data to be written to the + * Serial Flash */ + u32 NumBytes; /**< Number of bytes to be written to the Serial + * Flash */ +} XIsf_WriteParam; + + +/** + * The following structure definition specifies the operational parameters to be + * passed to the XIsf_Read API while performing Normal Read (XISF_READ), + * Fast Read (XISF_FAST_READ) and OTP Read (XISF_OTP_READ) operations . + */ +typedef struct { + u32 Address; /**< Start address in the Serial Flash */ + u8 *ReadPtr; /**< Read buffer pointer where data needs to be + * stored */ + u32 NumBytes; /**< Number of bytes to read */ + int NumDummyBytes; /**< Number of dummy bytes associated with the + * fast read command. Valid only for dual o/p + * fast read, dual i/o fast read, quad o/p + * fast read and quad i/o fast read */ +} XIsf_ReadParam; + +/** + * The following structure definition specifies the operational parameters to + * be passed to the XIsf_Write API while writing data to the internal SRAM + * buffer of the Atmel Serial Flash (XISF_BUFFER_WRITE). + */ +typedef struct { + u8 BufferNum; /**< SRAM buffer number of Serial Flash */ + u8 *WritePtr; /**< Pointer to the data to be written into the + * Serial Flash SRAM Buffer */ + u32 ByteOffset; /**< Byte offset in the buffer from which the + * data is written */ + u32 NumBytes; /**< Number of bytes to be written into the + * buffer */ +} XIsf_BufferWriteParam; + +/** + * The following structure definition specifies the operational parameters to be + * passed to the XIsf_Write API while writing data from the internal SRAM buffer + * to a Page in the Atmel Serial Flash using XISF_BUF_TO_PAGE_WRITE_WITH_ERASE / + * XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE commands in Atmel Serial Flash. + */ +typedef struct { + u8 BufferNum; /**< SRAM buffer number of Serial Flash */ + u32 Address; /**< Starting address in the Serial Flash */ +} XIsf_BufferToFlashWriteParam; + +/** + * The following structure definition specifies the operational parameters to be + * passed to the XIsf_Read API while performing Page to Buffer Transfer + * operation (XISF_PAGE_TO_BUF_TRANS) in Atmel Serial Flash. + */ +typedef struct { + u8 BufferNum; /**< SRAM buffer number of Serial Flash */ + u32 Address; /**< Start address in the Serial Flash */ +} XIsf_FlashToBufTransferParam; + +/** + * The following structure definition specifies operational parameters to be + * passed to the XIsf_Read API while reading data from the Internal SRAM buffer + * of Flash using XISF_BUFFER_READ or XISF_FAST_BUFFER_READ commands in Atmel + * Serial Flash. + */ +typedef struct { + u8 BufferNum; /**< SRAM buffer number of Serial Flash */ + u8 *ReadPtr; /**< Read buffer pointer where data read from + * the SRAM buffer is stored */ + u32 ByteOffset; /**< Byte offset in the SRAM buffer from where + * the first byte is read */ + u32 NumBytes; /**< Number of bytes to be read from the + * buffer */ +} XIsf_BufferReadParam; + + +/************************** Variable Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This API sets the interrupt/polling mode of transfer. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Mode is the value to be set. +* +* @note By default, the xilisf library is designed to operate in +* polling mode. User needs to call this API to set in interrupt +* mode, if operating in Interrupt Mode. +******************************************************************************/ +static inline void XIsf_SetTransferMode(XIsf *InstancePtr, u8 Mode) +{ + InstancePtr->IntrMode = Mode; +} + +/*****************************************************************************/ +/** +* +* This API gets the interrupt/polling mode of transfer. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @note (shakti) +******************************************************************************/ +static inline u8 XIsf_GetTransferMode(XIsf *InstancePtr) +{ + return(InstancePtr->IntrMode); +} + +/************************** Function Prototypes ******************************/ + +/* + * Initialization Function. + */ +int XIsf_Initialize(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, u8 SlaveSelect, + u8 *WritePtr); + +/* + * Function to read the Status Registers. + */ +int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr); + +#if (XPAR_XISF_FLASH_FAMILY == WINBOND) +int XIsf_GetStatusReg2(XIsf *InstancePtr, u8 *ReadPtr); +#endif + + +/* + * Function to read the Serial Flash information. + */ +int XIsf_GetDeviceInfo(XIsf *InstancePtr, u8 *ReadPtr); + +/* + * Function for Writing to the Serial Flash. + */ +int XIsf_Write(XIsf *InstancePtr, XIsf_WriteOperation Operation, + void *OpParamPtr); + +/* + * Function for Reading from the Serial Flash. + */ +int XIsf_Read(XIsf *InstancePtr, XIsf_ReadOperation Operation, + void *OpParamPtr); + +/* + * Function for Erasing the Serial Flash. + */ +int XIsf_Erase(XIsf *InstancePtr, XIsf_EraseOperation Operation, u32 Address); + +#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) \ + || (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) +/* + * Function for entering into 4 byte mode for Micron flash. + */ +int XIsf_MicronFlashEnter4BAddMode(XIsf *InstancePtr); + +/* + * Function for exiting from 4 byte mode for Micron flash. + */ +int XIsf_MicronFlashExit4BAddMode(XIsf *InstancePtr); +#endif +/* + * Function related to Sector protection. + */ +int XIsf_SectorProtect(XIsf *InstancePtr, XIsf_SpOperation Operation, + u8 *BufferPtr); + +/* + * Function to perform different control operations. + */ +int XIsf_Ioctl(XIsf *InstancePtr, XIsf_IoctlOperation Operation); + +/* + * Function for Enabling/Disabling Write to Intel, STM, Winbond and Spansion + * Serial Flash. + */ +int XIsf_WriteEnable(XIsf *InstancePtr, u8 WriteEnable); + +/* + * Function for Registering Interfaces SPI, PSQSPI, PSSPI + */ +void XIsf_RegisterInterface(XIsf *InstancePtr); + +/* + * Function for setting SPI/PSQSPI/PSSPI Configuration + */ +int XIsf_SetSpiConfiguration(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, + u32 Options, u8 PreScaler); + +/* + *Interrupt Status Handler of XilIsf Lib + */ +void XIsf_SetStatusHandler(XIsf *InstancePtr, XIsf_Iface *XIfaceInstancePtr, + XIsf_StatusHandler XilIsf_Handler); + +/* + *Interrupt Handler of XilISF Lib + */ +void XIsf_IfaceHandler(void *CallBackRef, u32 StatusEvent, + unsigned int ByteCount); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilisf/src/include/xilisf_atmel.h b/lib/sw_services/xilisf/src/include/xilisf_atmel.h new file mode 100644 index 00000000..a242aff1 --- /dev/null +++ b/lib/sw_services/xilisf/src/include/xilisf_atmel.h @@ -0,0 +1,268 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_atmel.h +* +* This file contains the definitions to be used when accessing the Atmel +* AT45XXXD Serial Flash. +* If any new definitions are added to this file, check if they need to be +* added to the xilisf_intelstm.h file too. +* +* @note None +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+*
+* 
+* +******************************************************************************/ +#ifndef XILISF_ATMEL_H /* prevent circular inclusions */ +#define XILISF_ATMEL_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +/** + * The following definitions specify the Device Id for the different Atmel + * AT45XXXD Serial Flash Devices. + */ +#define XISF_ATMEL_DEV_AT45DB011D 0x22 /**< Device ID of AT45DB011D */ +#define XISF_ATMEL_DEV_AT45DB021D 0x23 /**< Device ID of AT45DB027D */ +#define XISF_ATMEL_DEV_AT45DB041D 0x24 /**< Device ID of AT45DB041D */ +#define XISF_ATMEL_DEV_AT45DB081D 0x25 /**< Device ID of AT45DB081D */ +#define XISF_ATMEL_DEV_AT45DB161D 0x26 /**< Device ID of AT45DB161D */ +#define XISF_ATMEL_DEV_AT45DB321D 0x27 /**< Device ID of AT45DB321D */ +#define XISF_ATMEL_DEV_AT45DB642D 0x28 /**< Device ID of AT45DB642D */ + + +/** + * Definitions of Atmel Serial Flash Device geometry. + */ +#define XISF_BYTES256_PER_PAGE 256 /**< 256 Bytes per Page */ +#define XISF_BYTES264_PER_PAGE 264 /**< 264 Bytes per Page */ +#define XISF_BYTES512_PER_PAGE 512 /**< 512 Bytes per Page */ +#define XISF_BYTES528_PER_PAGE 528 /**< 528 Bytes per Page */ +#define XISF_BYTES1024_PER_PAGE 1024 /**< 1024 Bytes per Page */ +#define XISF_BYTES1056_PER_PAGE 1056 /**< 1056 Bytes per Page */ +#define XISF_PAGES8_PER_BLOCK 8 /**< Pages per Block */ +#define XISF_BLOCKS16_PER_SECTOR 16 /**< 16 Blocks per Sector */ +#define XISF_BLOCKS32_PER_SECTOR 32 /**< 32 Blocks per Sector */ +#define XISF_NUM_OF_SECTORS4 4 /**< 4 Sectors */ +#define XISF_NUM_OF_SECTORS8 8 /**< 8 Sectors */ +#define XISF_NUM_OF_SECTORS16 16 /**< 16 Sectors */ +#define XISF_NUM_OF_SECTORS32 32 /**< 32 Sectors */ +#define XISF_NUM_OF_SECTORS64 64 /**< 64 Sectors */ + +/** + * Definitions of Bit masks used for calculating device address from a + * linear address in the case of Default Addressing mode . + */ +#define XISF_BYTES256_PER_PAGE_MASK 0x0FF /**< Byte mask for devices with + * 256 or less bytes per page + */ +#define XISF_BYTES512_PER_PAGE_MASK 0x1FF /**< Byte mask for devices with + * more than 256 bytes per + * page */ +#define XISF_BYTES1024_PER_PAGE_MASK 0x3FF /**< Byte mask for devices with + * more than 512 bytes per + * page */ +#define XISF_BYTES2048_PER_PAGE_MASK 0x7FF /**< Byte mask for devices with + * more than 1024 bytes per + * page */ + +/** + * Definitions of Read commands. + */ +#define XISF_CMD_RANDOM_READ 0x03 /**< Random Read command */ +#define XISF_CMD_FAST_READ 0x0B /**< Fast Read command */ +#define XISF_CMD_ISFINFO_READ 0x9F /**< Device Info command */ +#define XISF_CMD_PAGETOBUF1_TRANS 0x53 /**< Transfer contents of a Page + * to the Buffer 1 command */ +#define XISF_CMD_PAGETOBUF2_TRANS 0x55 /**< Transfer contents of a Page + * to the Buffer 2 command */ +#define XISF_CMD_BUF1_READ 0xD1 /**< Buffer 1 Read command */ +#define XISF_CMD_BUF2_READ 0xD3 /**< Buffer 2 Read command */ +#define XISF_CMD_FAST_BUF1_READ 0xD4 /**< Fast Buffer 1 Read Cmd */ +#define XISF_CMD_FAST_BUF2_READ 0xD6 /**< Fast Buffer 2 Read Cmd */ +#define XISF_CMD_STATUSREG_READ 0xD7 /**< Status Greg Read Cmd */ + +/** + * Definitions of Write commands. + */ +#define XISF_CMD_PAGEPROG_WRITE 0x82 /**< Page Program command */ +#define XISF_CMD_AUTOPAGE_WRITE 0x58 /**< Auto write command */ +#define XISF_CMD_BUFFER1_WRITE 0x84 /**< Buffer1 write command */ +#define XISF_CMD_BUFFER2_WRITE 0x87 /**< Buffer2 write command */ +#define XISF_CMD_ERASE_BUF1TOPAGE_WRITE 0x83 /**< Erase page first then write + * buffer 1 to the page + * command */ +#define XISF_CMD_ERASE_BUF2TOPAGE_WRITE 0x86 /**< Erase page first then write + * buffer2 to the page + * command */ +#define XISF_CMD_BUF1TOPAGE_WRITE 0x88 /**< Write buffer1 to the page + * command without Erase */ +#define XISF_CMD_BUF2TOPAGE_WRITE 0x89 /**< Write buffer2 to the page + * command without Erase */ + +/** + * Definitions of Erase commands. + */ +#define XISF_CMD_PAGE_ERASE 0x81 /**< Page Erase command */ +#define XISF_CMD_BLOCK_ERASE 0x50 /**< Block erase command */ +#define XISF_CMD_SECTOR_ERASE 0x7C /**< Sector Erase command */ + +/** + * Definitions of commands used for + * - Erasing SPR + * - Programming SPR + * - Enabling/Disabling SPR. + */ +#define XISF_CMD_SPR_BYTE1 0x3D /**< SPR command byte1 */ +#define XISF_CMD_SPR_BYTE2 0x2A /**< SPR command byte2 */ +#define XISF_CMD_SPR_BYTE3 0x7F /**< SPR command byte3 */ +#define XISF_CMD_SPR_BYTE4_ERASE 0xCF /**< SPR erase command */ +#define XISF_CMD_SPR_BYTE4_PROGRAM 0xFC /**< SPR program command */ +#define XISF_CMD_SPR_BYTE4_ENABLE 0xA9 /**< SPR enable command */ +#define XISF_CMD_SPR_BYTE4_DISABLE 0x9A /**< SPR disable command */ + +/** + * Definitions of command used for reading SPR. + */ +#define XISF_CMD_SPR_READ 0x32 /**< SPR read command */ + +/** + * The following definitions specify the buffer number of Atmel Serial Flash. + */ +#define XISF_PAGE_BUFFER1 1 /**< Buffer 1 */ +#define XISF_PAGE_BUFFER2 2 /**< Buffer 2 */ + + +/** + * The following definitions specify the Status Register bit definitions of + * Atmel Serial Flash. + */ +#define XISF_SR_ADDR_MODE_MASK 0x01 /**< Address mode mask */ +#define XISF_SR_COMPARE_MASK 0x40 /**< Compare mask */ +#define XISF_SR_IS_READY_MASK 0x80 /**< Ready mask */ +#define XISF_SR_DEVID_MASK 0x2C /**< Device ID mask */ +#define XISF_SR_DEVID_SHIFT_MASK 0x02 /**< Device ID shift mask */ + +/** + * The following definitions determine the addressing mode of the Atmel Serial + * Flash. + */ +#define XISF_POWEROFTWO_ADDRESS 0x01 /**< Pow-Of-2 address mask */ +#define XISF_DEFAULT_ADDRESS 0x00 /**< Default address mask */ + +/** + * This definitions specify the extra bytes in each of the Write command, Read + * command, Erase command, commands operating on SPR, auto page write, page to + * buffer and buffer to page transfer commands. This count includes + * Command byte, address bytes and any don't care bytes needed. + */ +#define XISF_CMD_SEND_EXTRA_BYTES 4 /**< Command extra bytes */ + +/** + * This definition specifies the extra bytes in each of the Write/Read/Erase + * commands, commands operating on SPR, auto page write, page to + * buffer and buffer to page transfer commands in 4 bytes addressing mode. + * This count includes Command byte, Address bytes and any + * don't care bytes needed. + */ +#define XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE 5 /**< Command extra bytes */ + +/** + * This definitions specify the extra bytes in Fast read Fast buffer read + * commands. This count includes Command byte, address bytes and any don't care + * bytes needed. + */ +#define XISF_CMD_FAST_READ_EXTRA_BYTES 5 /**< Fast read and Fast buffer + * read extra bytes */ + +/** + * The following definitions specify the total bytes in some of the commands. + * This count includes Command byte and any don't care bytes needed. + */ +#define XISF_STATUS_RDWR_BYTES 2 /**< Status Read/Write bytes + * count */ +#define XISF_INFO_READ_BYTES 5 /**< Flash Info Read bytes + * count */ +#define XISF_INFO_EXTRA_BYTES 1 /**< Flash Info Read Extra + * bytes */ +#define XISF_CMD_MAX_EXTRA_BYTES 5 /**< Max extra bytes for + * all commands */ +#define XISF_DUMMYBYTE 0xFF /**< Dummy byte to fill */ + + +/** + * Address Shift Masks. + */ +#define XISF_ADDR_SHIFT16 16 /**< 16 bit Shift */ +#define XISF_ADDR_SHIFT8 8 /**< 8 bit Shift */ + + +/** + * Byte Positions. + */ +#define BYTE1 0 /**< Byte 1 position */ +#define BYTE2 1 /**< Byte 2 position */ +#define BYTE3 2 /**< Byte 3 position */ +#define BYTE4 3 /**< Byte 4 position */ +#define BYTE5 4 /**< Byte 5 position */ + + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilisf/src/include/xilisf_intelstm.h b/lib/sw_services/xilisf/src/include/xilisf_intelstm.h new file mode 100644 index 00000000..429853b7 --- /dev/null +++ b/lib/sw_services/xilisf/src/include/xilisf_intelstm.h @@ -0,0 +1,365 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_intelstm.h +* +* This file contains the definitions to be used when accessing the Intel, STM, +* Winbond and Spansion Serial Flash. +* If any new definitions are added to this file, check if they need to be +* added to the xilisf_atmel.h file too. +* +* @note None +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+* 2.01a sdm      01/04/10 Added Support for Winbond W25QXX/W25XX devices
+* 2.04a sdm      08/17/10 Updated to support Numonyx (N25QXX) and Spansion
+*			  flash memories
+* 3.00a srt	 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
+*			  Added support to SST flash on SPI PS interface.
+* 3.02a srt	 04/26/13 Modified SECTOR and BLOCK Erase commands for
+*			  SST flash (CR 703816).
+* 5.2   asa  05/12/15 Added macros for 4 byte commands.
+* 
+* +******************************************************************************/ +#ifndef XILISF_INTELSTM_H /* prevent circular inclusions */ +#define XILISF_INTELSTM_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +/************************** Constant Definitions *****************************/ + +/** + * The following definitions specify the Device Id for the different + * Intel (Numonyx) S33 Serial Flash devices. + */ +#define XISF_INTEL_DEV_S3316MBIT 0x11 /**< Device ID for 16Mbit */ +#define XISF_INTEL_DEV_S3332MBIT 0x12 /**< Device ID for 32Mbit */ +#define XISF_INTEL_DEV_S3364MBIT 0x13 /**< Device ID for 64Mbit */ + +/** + * The following definitions specify the Device Id for the different + * STM (Numonyx) M25PXX Serial Flash devices. + */ +#define XISF_STM_DEV_M25P05_A 0x2010 /**< Device ID for M25P05-A */ +#define XISF_STM_DEV_M25P10_A 0x2011 /**< Device ID for M25P10-A */ +#define XISF_STM_DEV_M25P20 0x2012 /**< Device ID for M25P20 */ +#define XISF_STM_DEV_M25P40 0x2013 /**< Device ID for M25P40 */ +#define XISF_STM_DEV_M25P80 0x2014 /**< Device ID for M25P80 */ +#define XISF_STM_DEV_M25P16 0x2015 /**< Device ID for M25P16 */ +#define XISF_STM_DEV_M25P32 0x2016 /**< Device ID for M25P32 */ +#define XISF_STM_DEV_M25P64 0x2017 /**< Device ID for M25P64 */ +#define XISF_STM_DEV_M25P128 0x2018 /**< Device ID for M25P128 */ + +/** + * The following definitions specify the Device Id (memory type/capacity) + * for the different Winbond W25QX/W25XX Serial Flash devices. + */ +#define XISF_WB_DEV_W25Q80 0x4014 /**< Device ID for W25Q80 */ +#define XISF_WB_DEV_W25Q16 0x4015 /**< Device ID for W25Q16 */ +#define XISF_WB_DEV_W25Q32 0x4016 /**< Device ID for W25Q32 */ +#define XISF_WB_DEV_W25Q64 0x4017 /**< Device ID for W25Q64 */ +#define XISF_WB_DEV_W25Q128 0x4018 /**< Device ID for W25Q128 */ +#define XISF_WB_DEV_W25X10 0x3011 /**< Device ID for W25X10 */ +#define XISF_WB_DEV_W25X20 0x3012 /**< Device ID for W25X20 */ +#define XISF_WB_DEV_W25X40 0x3013 /**< Device ID for W25X40 */ +#define XISF_WB_DEV_W25X80 0x3014 /**< Device ID for W25X80 */ +#define XISF_WB_DEV_W25X16 0x3015 /**< Device ID for W25X16 */ +#define XISF_WB_DEV_W25X32 0x3016 /**< Device ID for W25X32 */ +#define XISF_WB_DEV_W25X64 0x3017 /**< Device ID for W25X64 */ + +/** + * The following definitions specify the Device Id (memory type/capacity) + * for the different STM (Numonyx) N25QXX Serial Flash devices. + */ +#define XISF_NM_DEV_N25Q32 0xBA16 /**< Device ID for N25Q32 */ +#define XISF_NM_DEV_N25Q64 0xBA17 /**< Device ID for N25Q64 */ +#define XISF_NM_DEV_N25Q128 0xBA18 /**< Device ID for N25Q128 */ +#define XISF_MIC_DEV_N25Q128 0xBB18 /**< Device ID for N25Q128 */ +#define XISF_MIC_DEV_N25Q256_3V0 0xBA19 +#define XISF_MIC_DEV_N25Q256_1V8 0xBB19 + +/** + * The following definitions specify the Device Id for the different + * Spansion S25FLXX Serial Flash devices. + */ +#define XISF_SPANSION_DEV_S25FL004 0x0212 /**< Device ID for S25FL004 */ +#define XISF_SPANSION_DEV_S25FL008 0x0213 /**< Device ID for S25FL008 */ +#define XISF_SPANSION_DEV_S25FL016 0x0214 /**< Device ID for S25FL016 */ +#define XISF_SPANSION_DEV_S25FL032 0x0215 /**< Device ID for S25FL032 */ +#define XISF_SPANSION_DEV_S25FL064 0x0216 /**< Device ID for S25FL064 */ +#define XISF_SPANSION_DEV_S25FL128 0x2018 /**< Device ID for S25FL128 + * and S25FL129 */ + +/** + * The following definitions specify the Device Id for the different + * SST Serial Flash device. + */ +#define XISF_SST_DEV_SST25WF080 0x2505 /**< Device ID for SST25WF080 */ + +/** + * Definitions for Intel, STM, Winbond and Spansion Serial Flash Device + * geometry. + */ +#define XISF_BYTES256_PER_PAGE 256 /**< 256 Bytes per Page */ +#define XISF_PAGES16_PER_SECTOR 16 /**< 16 Pages per Sector */ +#define XISF_PAGES128_PER_SECTOR 128 /**< 128 Pages per Sector */ +#define XISF_PAGES256_PER_SECTOR 256 /**< 256 Pages per Sector */ +#define XISF_PAGES1024_PER_SECTOR 1024 /**< 1024 Pages per Sector */ +#define XISF_NUM_OF_SECTORS2 2 /**< 2 Sectors */ +#define XISF_NUM_OF_SECTORS4 4 /**< 4 Sectors */ +#define XISF_NUM_OF_SECTORS8 8 /**< 8 Sector */ +#define XISF_NUM_OF_SECTORS16 16 /**< 16 Sectors */ +#define XISF_NUM_OF_SECTORS32 32 /**< 32 Sectors */ +#define XISF_NUM_OF_SECTORS64 64 /**< 64 Sectors */ +#define XISF_NUM_OF_SECTORS128 128 /**< 128 Sectors */ +#define XISF_NUM_OF_SECTORS256 256 /**< 256 Sectors */ +#define XISF_NUM_OF_SECTORS512 512 /**< 512 Sectors */ +#define XISF_NUM_OF_SECTORS1024 1024 /**< 1024 Sectors */ +#define XISF_NUM_OF_SECTORS2048 2048 /**< 2048 Sectors */ +#define XISF_NUM_OF_SECTORS4096 4096 /**< 4096 Sectors */ + +/** + * Definitions of Read commands. + */ +#define XISF_CMD_RANDOM_READ 0x03 /**< Random Read command */ +#define XISF_CMD_RANDOM_READ_4BYTE 0x13 /**< Random 4 byte Read command */ +#define XISF_CMD_FAST_READ 0x0B /**< Fast Read command */ +#define XISF_CMD_FAST_READ_4BYTE 0x0C /**< 4 byte Fast Read command */ +#define XISF_CMD_ISFINFO_READ 0x9F /**< Device Info command */ +#define XISF_CMD_STATUSREG_READ 0x05 /**< Status Reg Read command */ +#define XISF_CMD_STATUSREG2_READ 0x35 /**< Status Reg2 Read command */ +#define XISF_CMD_DUAL_OP_FAST_READ 0x3B /**< Dual output fast read */ +#define XISF_CMD_DUAL_OP_FAST_READ_4B 0x3C /**< 4 byte Dual output fast read */ +#define XISF_CMD_DUAL_IO_FAST_READ 0xBB /**< Dual i/o fast read */ +#define XISF_CMD_DUAL_IO_FAST_READ_4B 0xBC /**< 4 byte Dual i/o fast read */ +#define XISF_CMD_QUAD_OP_FAST_READ 0x6B /**< Quad output fast read */ +#define XISF_CMD_QUAD_OP_FAST_READ_4B 0x6C /**< 4 byte Quad output fast read */ +#define XISF_CMD_QUAD_IO_FAST_READ 0xEB /**< Quad i/o fast read */ +#define XISF_CMD_QUAD_IO_FAST_READ_4B 0xEC /**< 4 byte Quad i/o fast read */ + +/** + * Definitions of Write commands. + */ +#define XISF_CMD_PAGEPROG_WRITE 0x02 /**< Page Program command */ +#define XISF_CMD_PAGEPROG_WRITE_4BYTE 0x12 /**< 4 byte Page Program command */ +#define XISF_CMD_STATUSREG_WRITE 0x01 /**< Status Reg Write Command */ +#define XISF_CMD_DUAL_IP_PAGE_WRITE 0xA2 /**< Dual input fast page write + */ +#define XISF_CMD_DUAL_IP_EXT_PAGE_WRITE 0xD2 /**< Dual input extended fast + * page write */ +#define XISF_CMD_QUAD_IP_PAGE_WRITE 0x32 /**< Quad input fast page write + */ +#define XISF_CMD_QUAD_IP_EXT_PAGE_WRITE 0x12 /**< Dual input extended fast + * page write */ + +/** + * Definitions of Erase commands. + */ +#define XISF_CMD_BULK_ERASE 0xC7 /**< Bulk Erase command */ + + +#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) +#define XISF_CMD_SECTOR_ERASE 0xD8 /**< Sector Erase command */ +#define XISF_CMD_SUB_SECTOR_ERASE 0x20 /**< Sub-sector Erase command. + * only for N25QXX */ +#define XISF_CMD_4BYTE_SECTOR_ERASE 0xDC +#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY == STM) || + (XPAR_XISF_FLASH_FAMILY == SPANSION)) */ + +#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST)) +#define XISF_CMD_BLOCK_ERASE 0xD8 /**< Block Erase command */ +#define XISF_CMD_SECTOR_ERASE 0x20 /**< Sector Erase command */ +#endif + +/** + * Definitions of commands used for + * - Write Enable/Disable. + * - Deep Power Down mode Enter/Release. + * - Switch to 4 byte addressing + */ +#define XISF_CMD_ENABLE_WRITE 0x06 /**< Write enable command */ +#define XISF_CMD_DISABLE_WRITE 0x04 /**< Write disable command */ +#define XISF_CMD_DEEP_POWER_DOWN 0xB9 /**< Enter DPD mode command */ +#define XISF_CMD_RELEASE_FROM_DPD 0xAB /**< Release DPD mode command */ + +#define XISF_CMD_ENABLE_HPM 0xA3 /**< Enable high performance + * mode */ + +#if (XPAR_XISF_FLASH_FAMILY == SPANSION) +#define XISF_CMD_ENTER_4BYTE_ADDR_MODE 0xB7 +#define XISF_CMD_EXIT_4BYTE_ADDR_MODE 0xE9 +#endif +#if (XPAR_XISF_FLASH_FAMILY == INTEL) +/** + * Definitions of commands which are only supported in Intel Serial Flash. + */ +#define XISF_CMD_OTP_READ 0x4B /**< OTP data read command */ +#define XISF_CMD_OTP_WRITE 0x42 /**< OTP write command */ +#define XISF_CMD_PARAM_BLOCK_ERASE 0x40 /**< Parameter Block Erase + * command */ +#define XISF_CMD_CLEAR_SRFAIL_FLAGS 0x30 /**< Clear SR fail bits Cmd */ +#define XISF_OTP_RDWR_EXTRA_BYTES 0x05 /**< OTP Read/Write + * extra bytes */ +#endif /* INTEL */ + + +/** + * The following definitions specify the Status Register bit definitions of + * Intel, STM, Winbond and Spansion Serial Flash. + */ +#define XISF_SR_IS_READY_MASK 0x01 /**< Ready mask */ +#define XISF_SR_WRITE_ENABLE_MASK 0x02 /**< Write Enable latch mask */ +#define XISF_SR_BLOCK_PROTECT_MASK 0x1C /**< Block Protect mask */ +#define XISF_SR_WRITE_PROTECT_MASK 0x80 /**< Status Reg write + * protect mask */ +#define XISF_SR_BLOCK_PROTECT_SHIFT 2 /**< Block protect bits shift */ + +#if (XPAR_XISF_FLASH_FAMILY == INTEL) +#define XISF_SR_PROG_FAIL_MASK 0x40 /**< Program Fail bit mask */ +#define XISF_SR_ERASE_FAIL_MASK 0x20 /**< Erase Fail bit mask */ +#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */ + +#if (XPAR_XISF_FLASH_FAMILY == WINBOND) +#define XISF_SR_TB_PROTECT_MASK 0x20 /**< Top/Bottom Write Protect */ +#define XISF_SR_SECTOR_PROTECT_MASK 0x40 /**< Sector Protect mask */ +#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */ + + +/** + * The definition specifies the total bytes in Bulk Erase commands. + * This count includes Command byte and any don't care bytes needed. + */ +#define XISF_BULK_ERASE_BYTES 0x01 /**< Bulk erase extra bytes */ + +/** + * The following definitions specify the Write Enable and Disable operation + * arguments to be passed to the XIsf_WriteEnable API. + */ +#define XISF_WRITE_ENABLE 1 /**< Write enable */ +#define XISF_WRITE_DISABLE 0 /**< Write disable */ + +/** + * This definition specifies the extra bytes in each of the Write Enable/Disable + * commands. This count includes Command byte, address bytes and any don't care + * bytes needed. + */ +#define XISF_CMD_WRITE_ENABLE_DISABLE_BYTES 1 /**< Write enable/disable + * command extra bytes */ + +/** + * This definition specifies the extra bytes in 4 byte addr mode enter and exit + * commands. This count refers to the Command byte. + */ +#define XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES 1 /**< Four byte addr mode + * command extra bytes */ +/** + * This definition specifies the extra bytes in each of the Write/Read/Erase + * commands, commands operating on SPR, auto page write, page to + * buffer and buffer to page transfer commands. This count includes + * Command byte, Address bytes and any don't care bytes needed. + */ +#define XISF_CMD_SEND_EXTRA_BYTES 4 /**< Command extra bytes */ + +/** + * This definition specifies the extra bytes in each of the Write/Read/Erase + * commands, commands operating on SPR, auto page write, page to + * buffer and buffer to page transfer commands in 4 bytes addressing mode. + * This count includes Command byte, Address bytes and any + * don't care bytes needed. + */ +#define XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE 5 /**< Command extra bytes */ + +/** + * This definition specifies the extra bytes in Fast Read and Fast Buffer Read + * commands. This count includes Command byte, address bytes and any don't care + * bytes needed. + */ +#define XISF_CMD_FAST_READ_EXTRA_BYTES 5 /**< Fast read and Fast buffer + * read extra bytes */ + +/** + * The following definitions specify the total bytes in some of the commands. + * This count includes Command byte and any don't care bytes needed. + */ +#define XISF_STATUS_RDWR_BYTES 2 /**< Status Read/Write bytes + * count */ +#define XISF_INFO_READ_BYTES 5 /**< Serial Flash Info read + * bytes count */ +#define XISF_INFO_EXTRA_BYTES 1 /**< Serial Flash Info extra + * bytes */ +#define XISF_IOCTL_BYTES 1 /**< Serial Flash IOCTL bytes */ +#define XISF_HPM_BYTES 4 /**< Serial Flash HPM bytes */ +#define XISF_CMD_MAX_EXTRA_BYTES 5 /**< Max extra bytes for + * all commands */ +#define XISF_DUMMYBYTE 0xFF /**< Dummy byte to fill */ + +/** + * Address Shift Masks. + */ +#define XISF_ADDR_SHIFT24 24 /**< 24 bit Shift */ +#define XISF_ADDR_SHIFT16 16 /**< 16 bit Shift */ +#define XISF_ADDR_SHIFT8 8 /**< 8 bit Shift */ + +/** + * Byte Positions. + */ +#define BYTE1 0 /**< Byte 1 position */ +#define BYTE2 1 /**< Byte 2 position */ +#define BYTE3 2 /**< Byte 3 position */ +#define BYTE4 3 /**< Byte 4 position */ +#define BYTE5 4 /**< Byte 5 position */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilisf/src/xilisf.c b/lib/sw_services/xilisf/src/xilisf.c new file mode 100644 index 00000000..62ff99c2 --- /dev/null +++ b/lib/sw_services/xilisf/src/xilisf.c @@ -0,0 +1,1956 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf.c +* +* This file contains the library functions to initialize, control and read the +* device information of the Serial Flash devices. Refer xilisf.h for detailed +* description. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+* 1.00a sdm      07/02/08 Changed the initialization so that the SPI
+*			  Master works in Spi Mode 3 as the In-System Flash
+*			  works only in Spi Mode 3
+* 2.00a ktn	11/27/09 Updated to use HAL processor APIs/definitions
+* 2.01a sdm	01/04/10 Added Support for Winbond W25QXX/W25XX devices
+*			  The parameter PagesPerBlock in the struct
+*			  IntelStmDeviceGeometry has been renamed to
+*			  PagesPerSector.
+* 2.03a sdm      04/17/10 Updated to support Winbond memory W25Q128.
+* 2.04a sdm      08/17/10 Updated to support Numonyx (N25QXX) and Spansion
+*			  flash memories
+* 3.00a srt	 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
+*			  New API:
+*			  	XIsf_RegisterInterface()
+*				XIsf_SetSpiConfiguration()
+*				XIsf_SetTransferMode()
+*			  Changed API:
+*			 	XIsf_Initialize()
+*				XIsf_Transfer()
+*			  Added support to SST flash.
+* 3.01a srt	 02/06/13 Updated for changes made in QSPIPS driver
+*			  (CR 698107).
+* 5.0   sb	 08/05/14 Updated for support for > 128 MB flash for PSQSPI
+*			  Interface. Added Library Handler API which will
+*			  register to driver interrupts, based upon the
+*			  interface selected.
+*			  New API:
+*				SpaMicWinFlashInitialize()
+*				GetRealAddr()
+*				SendBankSelect()
+*				XIsf_SetStatusHandler()
+*				void XIsf_IfaceHandler()
+*			  Changed API:
+*				- XIsf_Initialize()
+*				Added Call back to lib interrupt handler
+*				after XIsf_Transfer Call
+*				- XIsf_Transfer()
+*				- XIsf_GetStatus()
+*				- XIsf_GetStatusReg2()
+*				- XIsf_GetDeviceInfo()
+*				- XIsf_WriteEnable()
+*				- XIsf_Ioctl()
+* 5.1   sb	 12/23/14 Added check for flash interface for Winbond, Spansion
+*			  and Micron flash family for PSQSPI.
+* 5.2   asa  05/12/15 Added APIs to support 4 byte addressing for Micron flash.
+*                     2 APIs were added, one to enter into 4 byte mode and the other
+*                     to exit from the same.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilisf.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) +/** + * The following structure specifies the geometry of the Atmel Serial Flash. + */ +typedef struct { + u8 DeviceCode; /**< Device code */ + u16 BytesPerPageDefaultMode; /**< Bytes per Page in Default mode */ + u16 BytesPerPagePowerOf2Mode; /**< Bytes per Page in PowerOf2 mode */ + u8 PagesPerBlock; /**< Number of Pages per Block */ + u8 BlocksPerSector; /**< Number of Blocks per Sector */ + u8 NumOfSectors; /**< Number of Sectors in the device */ +} AtmelDeviceGeometry; +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + +#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) \ + || (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) \ +/** + * The following structure specifies the geometry of the Intel/STM Serial Flash. + */ +typedef struct { + u8 ManufacturerID; /**< Manufacturer code */ + u16 DeviceCode; /**< Device code */ + u16 BytesPerPage; /**< Bytes per Page */ + u16 PagesPerSector; /**< Number of Pages per Sector */ + u16 NumOfSectors; /**< Number of Sectors in the device */ +} IntelStmDeviceGeometry; +#endif /* (((XPAR_XISF_FLASH_FAMILY == INTEL) || + (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ + +#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) +/** + * The following structure specifies the geometry of the Spansion/Micron + * Serial Flash. + */ +typedef struct { + u32 SectSize; /**< Individual sector size or + * combined sector size in case of parallel + * config*/ + u32 NumSect; /**< Total no. of sectors in one/two + * flash devices */ + u32 PageSize; /**< Individual page size or + * combined page size in case of parallel + * config*/ + u32 NumPage; /**< Total no. of pages in one/two flash + * devices */ + u32 FlashDeviceSize; /**< This is the size of one flash device + * NOT the combination of both devices, + * if present */ + u8 ManufacturerID; /**< Manufacturer ID - used to identify make */ + u8 DeviceIDMemSize; /**< Byte of device ID indicating the memory + * size */ + u32 SectMask; /**< Mask to get sector start address */ + u8 NumDie; /**< No. of die forming a single flash */ +} SpaMicWinDeviceGeometry; + +#endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,u32 ByteCount); + +u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address); + +#ifdef XPAR_XISF_INTERFACE_PSQSPI +int SendBankSelect(XIsf *InstancePtr, u32 BankSel); +#endif + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) +static int AtmelFlashInitialize(XIsf *InstancePtr, u8 *ReadBuf); +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + +#if (((XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) +static int IntelStmFlashInitialize(XIsf *InstancePtr, u8 *ReadBuf); +#endif /* (((XPAR_XISF_FLASH_FAMILY == INTEL) || \ + (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) */ + +#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) +static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr); + +#endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + +/************************** Variable Definitions *****************************/ + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) +static const AtmelDeviceGeometry AtmelDevices[] = { + + {XISF_ATMEL_DEV_AT45DB011D, XISF_BYTES264_PER_PAGE, + XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK, + XISF_BLOCKS16_PER_SECTOR, XISF_NUM_OF_SECTORS4}, + + {XISF_ATMEL_DEV_AT45DB021D, XISF_BYTES264_PER_PAGE, + XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK, + XISF_BLOCKS16_PER_SECTOR, XISF_NUM_OF_SECTORS8}, + + {XISF_ATMEL_DEV_AT45DB041D, XISF_BYTES264_PER_PAGE, + XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK, + XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS8}, + + {XISF_ATMEL_DEV_AT45DB081D, XISF_BYTES264_PER_PAGE, + XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK, + XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS16}, + + {XISF_ATMEL_DEV_AT45DB161D, XISF_BYTES528_PER_PAGE, + XISF_BYTES512_PER_PAGE, XISF_PAGES8_PER_BLOCK, + XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS16}, + + {XISF_ATMEL_DEV_AT45DB321D, XISF_BYTES528_PER_PAGE, + XISF_BYTES512_PER_PAGE, XISF_PAGES8_PER_BLOCK, + XISF_BLOCKS16_PER_SECTOR, XISF_NUM_OF_SECTORS64}, + + {XISF_ATMEL_DEV_AT45DB642D, XISF_BYTES1056_PER_PAGE, + XISF_BYTES1024_PER_PAGE, XISF_PAGES8_PER_BLOCK, + XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS32} +}; +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + +#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) \ + || (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) +static const IntelStmDeviceGeometry IntelStmDevices[] = { + {XISF_MANUFACTURER_ID_INTEL, XISF_INTEL_DEV_S3316MBIT, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS32}, + + {XISF_MANUFACTURER_ID_INTEL, XISF_INTEL_DEV_S3332MBIT, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS64}, + + {XISF_MANUFACTURER_ID_INTEL, XISF_INTEL_DEV_S3364MBIT, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS128}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P05_A, + XISF_BYTES256_PER_PAGE, XISF_PAGES128_PER_SECTOR, + XISF_NUM_OF_SECTORS2}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P10_A, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS2}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P20, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS4}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P40, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS8}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P80, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS16}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P16, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS32}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P32, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS64}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P64, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS128}, + + {XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P128, + XISF_BYTES256_PER_PAGE, XISF_PAGES1024_PER_SECTOR, + XISF_NUM_OF_SECTORS64}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q80, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS256}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q16, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS512}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q32, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS1024}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q64, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS2048}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q128, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS4096}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X10, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS32}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X20, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS64}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X40, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS128}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X80, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS256}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X16, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS512}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X32, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS1024}, + + {XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X64, + XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR, + XISF_NUM_OF_SECTORS2048}, + + {XISF_MANUFACTURER_ID_STM, XISF_NM_DEV_N25Q32, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS64}, + + {XISF_MANUFACTURER_ID_STM, XISF_NM_DEV_N25Q64, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS128}, + + {XISF_MANUFACTURER_ID_STM, XISF_NM_DEV_N25Q128, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS256}, + + {XISF_MANUFACTURER_ID_STM, XISF_MIC_DEV_N25Q128, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS256}, + + {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL004, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS8}, + + {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL008, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS16}, + + {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL016, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS32}, + + {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL032, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS64}, + + {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL064, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS128}, + + {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL128, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS256}, + + {XISF_MANUFACTURER_ID_SST, XISF_SST_DEV_SST25WF080, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS256}, + + {XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_N25Q256_3V0, + XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, + XISF_NUM_OF_SECTORS512}, + +}; +#endif /* (((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \ + || (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ + +#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) +static const SpaMicWinDeviceGeometry SpaMicWinDevices[] = { + {0x10000, 0x100, 256, 0x10000, 0x1000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_128, + 0xFFFF0000, 1}, + {0x10000, 0x200, 256, 0x20000, 0x1000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_128, + 0xFFFF0000, 1}, + {0x20000, 0x100, 512, 0x10000, 0x1000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_128, + 0xFFFE0000, 1}, + {0x10000, 0x200, 256, 0x20000, 0x2000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_256, + 0xFFFF0000, 1}, + {0x10000, 0x400, 256, 0x40000, 0x2000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_256, + 0xFFFF0000, 1}, + {0x20000, 0x200, 512, 0x20000, 0x2000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_256, + 0xFFFE0000, 1}, + {0x40000, 0x100, 512, 0x20000, 0x4000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_512, + 0xFFFC0000, 1}, + {0x40000, 0x200, 512, 0x40000, 0x4000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_512, + 0xFFFC0000, 1}, + {0x80000, 0x100, 1024, 0x20000, 0x4000000, + XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_512, + 0xFFF80000, 1}, + /* Spansion 1Gbit is handled as 512Mbit stacked */ + /* Micron */ + {0x10000, 0x100, 256, 0x10000, 0x1000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_128, + 0xFFFF0000, 1}, + {0x10000, 0x200, 256, 0x20000, 0x1000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_128, + 0xFFFF0000, 1}, + {0x20000, 0x100, 512, 0x10000, 0x1000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_128, + 0xFFFE0000, 1}, + {0x10000, 0x200, 256, 0x20000, 0x2000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_256, + 0xFFFF0000, 1}, + {0x10000, 0x400, 256, 0x40000, 0x2000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_256, + 0xFFFF0000, 1}, + {0x20000, 0x200, 512, 0x20000, 0x2000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_256, + 0xFFFE0000, 1}, + {0x10000, 0x400, 256, 0x40000, 0x4000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_512, + 0xFFFF0000, 2}, + {0x10000, 0x800, 256, 0x80000, 0x4000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_512, + 0xFFFF0000, 2}, + {0x20000, 0x400, 512, 0x40000, 0x4000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_512, + 0xFFFE0000, 2}, + {0x10000, 0x800, 256, 0x80000, 0x8000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_1G, + 0xFFFF0000, 4}, + {0x10000, 0x1000, 256, 0x100000, 0x8000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_1G, + 0xFFFF0000, 4}, + {0x20000, 0x800, 512, 0x80000, 0x8000000, + XISF_MANUFACTURER_ID_MICRON, XISF_MICRON_ID_BYTE2_1G, + 0xFFFE0000, 4}, + /* Winbond */ + {0x10000, 0x100, 256, 0x10000, 0x1000000, + XISF_MANUFACTURER_ID_WINBOND, XISF_WINBOND_ID_BYTE2_128, + 0xFFFF0000, 1}, + {0x10000, 0x200, 256, 0x20000, 0x1000000, + XISF_MANUFACTURER_ID_WINBOND, XISF_WINBOND_ID_BYTE2_128, + 0xFFFF0000, 1}, + {0x20000, 0x100, 512, 0x10000, 0x1000000, + XISF_MANUFACTURER_ID_WINBOND, XISF_WINBOND_ID_BYTE2_128, + 0xFFFE0000, 1} +}; +#endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + +/* + * The following variables are shared between non-interrupt processing and + * interrupt processing such that they must be global. + */ +volatile unsigned int XIsf_TransferInProgress; +u32 XIsf_StatusEventInfo; +unsigned int XIsf_ByteCountInfo; +static u32 XIsf_FCTIndex; +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* The geometry of the underlying Serial Flash is determined by reading the +* Joint Electron Device Engineering Council (JEDEC) Device Information and +* the Status Register of the Serial Flash. +* This API when called initializes the SPI interface with default settings. +* With custom settings, user should call XIsf_SetSpiConfiguration() and then +* call this API. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param SpiInstPtr is a pointer to XIsf_Iface instance to be worked on. +* @param SlaveSelect is a 32-bit mask with a 1 in the bit position of +* slave being selected. Only one slave can be selected at a time. +* @param WritePtr is a pointer to the buffer allocated by the user to be +* used by the In-system and Serial Flash Library to perform any +* read/write operations on the Serial Flash device. +* User applications must pass the address of this buffer for the +* Library to work. +* - Write operations : +* - The size of this buffer should be equal to the Number +* of bytes to be written to the Serial Flash + +* XISF_CMD_MAX_EXTRA_BYTES. +* - The size of this buffer should be large enough for +* usage across all the applications that use a common +* instance of the Serial Flash. +* - A minimum of one byte and a maximum of ISF_PAGE_SIZE +* bytes can be written to the Serial Flash, through a +* single Write operation. +* - Read operations : +* - The size of this buffer should be equal to +* XISF_CMD_MAX_EXTRA_BYTES, if the application only reads +* from the Serial Flash (no write operations). +* +* @return - XST_SUCCESS if successful. +* - XST_DEVICE_IS_STOPPED if the device must be started before +* transferring data. +* - XST_FAILURE, otherwise. +* +* @note - The XIsf_Initialize() API is a blocking call (for both +* polled and interrupt modes of the Spi driver). It reads the +* JEDEC information of the device and waits till the transfer is +* complete before checking if the information is valid. +* - This library can support multiple instances of Serial Flash +* at a time, provided they are of the same device family (either +* Atmel, Intel or STM, Winbond or Spansion) as the device family +* is selected at compile time. +* +******************************************************************************/ +int XIsf_Initialize(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, u8 SlaveSelect, + u8 *WritePtr) +{ + int Status; + u8 ReadBuf[XISF_INFO_READ_BYTES + XISF_INFO_EXTRA_BYTES] = {0}; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (SpiInstPtr == NULL) { + return (int)(XST_FAILURE); + } + + if (WritePtr == NULL) { + return (int)(XST_FAILURE); + } + + InstancePtr->IsReady = FALSE; + InstancePtr->SpiSlaveSelect = SlaveSelect; + InstancePtr->WriteBufPtr = WritePtr; + +#ifdef XPAR_XISF_INTERFACE_AXISPI + if (SpiInstPtr->IsStarted != XIL_COMPONENT_IS_STARTED) { + return XST_DEVICE_IS_STOPPED; + } +#endif + + if ((!InstancePtr->RegDone) != 0) { + (void)XIsf_SetSpiConfiguration(InstancePtr, SpiInstPtr, + XISF_SPI_OPTIONS, XISF_SPI_PRESCALER); + } + + /* + * Get the JEDEC Device Info. + * The IsReady is temporarily made TRUE and + * transfer is set in polling mode to fetch the JEDEC Info. + */ + XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE); + InstancePtr->IsReady = TRUE; + Status = XIsf_GetDeviceInfo(InstancePtr, ReadBuf); + InstancePtr->IsReady = FALSE; + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + +#ifdef XPAR_XISF_INTERFACE_AXISPI + /* + * Wait until the transfer is complete. + */ + do { + Status = + InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr, + InstancePtr->SpiSlaveSelect); + } while(Status == XST_DEVICE_BUSY); + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + +#endif + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Check for Atmel Serial Flash. + */ + Status = AtmelFlashInitialize(InstancePtr, ReadBuf); + +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + +#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) \ + || (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + + /* + * Check for Intel/STM/Winbond/Spansion Serial Flash. + */ + Status = IntelStmFlashInitialize(InstancePtr, ReadBuf); + +#endif /* (((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \ + || (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ +#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) + + Status = SpaMicWinFlashInitialize(InstancePtr, ReadBuf); + +#endif /*(((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + + return Status; +} + + +/*****************************************************************************/ +/** +* +* This API sets the configuration of SPI. This will set the options and +* clock prescaler (if applicable). +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param SpiInstPtr is a pointer to XIsf_Iface instance to be worked on. +* @param Options contains specified options to be set. +* @param PreScaler is the value of the clock prescaler to set. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This API can be called before calling XIsf_Initialize() +* to initialize the SPI interface in other than default options +* mode. PreScaler is only applicable to PS SPI/QSPI. +* +******************************************************************************/ +int XIsf_SetSpiConfiguration(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, + u32 Options, u8 PreScaler) +{ + int Status; + + if ((!InstancePtr->RegDone) != 0) { + XIsf_RegisterInterface(InstancePtr); + InstancePtr->SpiInstPtr = SpiInstPtr; + InstancePtr->RegDone = TRUE; + } + + Status = InstancePtr->XIsf_Iface_SetOptions(InstancePtr->SpiInstPtr, + Options); + if (Status != (int)(XST_SUCCESS)){ + return (int)(XST_FAILURE); + } + + if ((InstancePtr->XIsf_Iface_SetClkPrescaler) != NULL) { + Status = InstancePtr->XIsf_Iface_SetClkPrescaler( + InstancePtr->SpiInstPtr, PreScaler); + if (Status != (int)(XST_SUCCESS)){ + return (int)(XST_FAILURE); + } + } + + return (int)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** +* +* This API reads the Serial Flash Status Register. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param ReadPtr is a pointer to the memory where the Status Register +* content is copied. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note The contents of the Status Register is stored at second byte +* pointed by the ReadPtr. +* +******************************************************************************/ +int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr) +{ + int Status; + u8 Mode; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_READ; + InstancePtr->WriteBufPtr[BYTE2] = XISF_DUMMYBYTE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr, + XISF_STATUS_RDWR_BYTES); + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + return (int)(XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This API reads the Serial Flash Status Register 2. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param ReadPtr is a pointer to the memory where the Status Register +* content is copied. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note The contents of the Status Register 2 is stored at the second +* byte pointed by the ReadPtr. +* This operation is available only in Winbond Serial Flash. +* +******************************************************************************/ +#if (XPAR_XISF_FLASH_FAMILY == WINBOND) +int XIsf_GetStatusReg2(XIsf *InstancePtr, u8 *ReadPtr) +{ + int Status; + u8 Mode; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG2_READ; + InstancePtr->WriteBufPtr[BYTE2] = XISF_DUMMYBYTE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr, + XISF_STATUS_RDWR_BYTES); + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + return (int)(XST_SUCCESS); +} +#endif + +/*****************************************************************************/ +/** +* +* This API reads the Joint Electron Device Engineering Council (JEDEC) +* information of the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param ReadPtr is a pointer to the buffer where the Device information +* is copied. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note The Device information is stored at the second byte pointed +* by the ReadPtr. +* +******************************************************************************/ +int XIsf_GetDeviceInfo(XIsf *InstancePtr, u8 *ReadPtr) +{ + int Status; + u8 Mode; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_ISFINFO_READ; + InstancePtr->WriteBufPtr[BYTE2] = XISF_DUMMYBYTE; + InstancePtr->WriteBufPtr[BYTE3] = XISF_DUMMYBYTE; + InstancePtr->WriteBufPtr[BYTE4] = XISF_DUMMYBYTE; + InstancePtr->WriteBufPtr[BYTE5] = XISF_DUMMYBYTE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + ReadPtr, XISF_INFO_READ_BYTES); + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This API Enables/Disables writes to the Intel, STM, Winbond and Spansion +* Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param WriteEnable specifies whether to Enable (XISF_CMD_ENABLE_WRITE) +* or Disable (XISF_CMD_DISABLE_WRITE) the writes to the +* Serial Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This API works only for Intel, STM, Winbond and Spansion Serial +* Flash. If this API is called for Atmel Flash, XST_FAILURE is +* returned. +* +******************************************************************************/ +int XIsf_WriteEnable(XIsf *InstancePtr, u8 WriteEnable) +{ + int Status = (int)(XST_FAILURE); + u8 Mode; + u8 WriteEnableBuf[1] = {0}; + u8 * NULLPtr = NULL; +#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST)) + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + if (WriteEnable == XISF_WRITE_ENABLE) { + + WriteEnableBuf[BYTE1] = XISF_CMD_ENABLE_WRITE; + + } else if (WriteEnable == XISF_WRITE_DISABLE) { + + WriteEnableBuf[BYTE1] = XISF_CMD_DISABLE_WRITE; + } else { + + return Status; + } + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, WriteEnableBuf, NULLPtr, + XISF_CMD_WRITE_ENABLE_DISABLE_BYTES); + + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + +#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION) || \ + (XPAR_XISF_FLASH_FAMILY == SST)) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This API configures and controls the Intel, STM, Winbond and Spansion Serial +* Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Operation is the type of Control operation to be performed +* on the Serial Flash. +* The different control operations are + - XISF_RELEASE_DPD: Release from Deep Power Down (DPD) Mode + - XISF_ENTER_DPD: Enter DPD Mode + - XISF_CLEAR_SR_FAIL_FLAGS: Clear Status Register Fail Flags +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - Atmel Serial Flash does not support any of these operations. +* - Intel Serial Flash support Enter/Release from DPD Mode and +* Clear Status Register Fail Flags. +* - STM, Winbond and Spansion Serial Flash support Enter/Release +* from DPD Mode. +* - Winbond (W25QXX) Serial Flash support Enable High Performance +* mode. +* +******************************************************************************/ +int XIsf_Ioctl(XIsf *InstancePtr, XIsf_IoctlOperation Operation) +{ + int Status; + u8 Mode; + u8* NULLPtr = NULL; + +#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST)) + u8 NumBytes; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + switch (Operation) { + case XISF_IOCTL_RELEASE_DPD: + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_RELEASE_FROM_DPD; + NumBytes = XISF_IOCTL_BYTES; + break; + + case XISF_IOCTL_ENTER_DPD: + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_DEEP_POWER_DOWN; + NumBytes = XISF_IOCTL_BYTES; + break; + +#if (XPAR_XISF_FLASH_FAMILY == INTEL) + case XISF_IOCTL_CLEAR_SR_FAIL_FLAGS: + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_CLEAR_SRFAIL_FLAGS; + NumBytes = XISF_IOCTL_BYTES; + break; +#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */ + +#if (XPAR_XISF_FLASH_FAMILY == WINBOND) + case XISF_IOCTL_ENABLE_HI_PERF_MODE: + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_ENABLE_HPM; + NumBytes = XISF_HPM_BYTES; + break; +#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */ + + default: + return (int)(XST_FAILURE); + } + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, + NumBytes); + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + +#else + Status = (int)(XST_FAILURE); + +#endif/* ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || + (XPAR_XISF_FLASH_FAMILY == SPANSION)) */ + + return Status; +} + +/*****************************************************************************/ +/* +* +* This function performs the SPI transfer. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param WritePtr is a pointer to the memory which contains the data to +* be transferred to the Serial Flash . +* @param ReadPtr is a pointer to the memory where the data read from the +* Serial Flash is stored. +* @param ByteCount is the number of bytes to be read from/written to the +* Serial Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This function is internal to the In-system and Serial Flash +* Library. It works with both interrupt mode and polled mode SPI +* transfers. In polled mode for AXI SPI, the user has to disable +* the Global Interrupts in the user application, after the Spi +* is Initialized and Spi driver is started +* +******************************************************************************/ +int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr, u32 ByteCount) +{ + int Status; + + /* + * Select the Serial Flash as a slave. + */ +#ifndef XPAR_XISF_INTERFACE_PSQSPI + Status = InstancePtr->XIsf_Iface_SetSlaveSelect( + InstancePtr->SpiInstPtr,InstancePtr->SpiSlaveSelect); +#else + Status = InstancePtr->XIsf_Iface_SetSlaveSelect( + InstancePtr->SpiInstPtr); +#endif + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + /* + * Start the transfer. + */ +#ifdef XPAR_XISF_INTERFACE_AXISPI + if (InstancePtr->IntrMode == XISF_INTERRUPT_MODE) { + XIsf_TransferInProgress = TRUE; + } + Status = InstancePtr->XIsf_Iface_Transfer(InstancePtr->SpiInstPtr, + WritePtr, ReadPtr, ByteCount); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IntrMode == XISF_INTERRUPT_MODE) { + while (XIsf_TransferInProgress != 0){ + /*NOP*/ + } + } + + return (int)(XST_SUCCESS); +#endif + + if (InstancePtr->IntrMode == XISF_INTERRUPT_MODE) { +#if defined(XPAR_XISF_INTERFACE_PSQSPI) || defined(XPAR_XISF_INTERFACE_PSSPI) + XIsf_TransferInProgress = TRUE; +#endif + Status = InstancePtr->XIsf_Iface_Transfer( + InstancePtr->SpiInstPtr, + WritePtr, ReadPtr, ByteCount); +#if defined(XPAR_XISF_INTERFACE_PSQSPI) || defined(XPAR_XISF_INTERFACE_PSSPI) + while (XIsf_TransferInProgress != 0){ + /*NOP*/ + } + +#endif + } else { + Status = InstancePtr->XIsf_Iface_PolledTransfer( + InstancePtr->SpiInstPtr, + WritePtr, ReadPtr, ByteCount); + } + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + return (int)(XST_SUCCESS); +} + + +/*****************************************************************************/ +/* +* +* This function registers the interface SPI/SPI PS/QSPI PS. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return None +* +* +******************************************************************************/ +void XIsf_RegisterInterface(XIsf *InstancePtr) +{ +#ifdef XPAR_XISF_INTERFACE_AXISPI + InstancePtr->XIsf_Iface_SetOptions = XSpi_SetOptions; + InstancePtr->XIsf_Iface_SetSlaveSelect = XSpi_SetSlaveSelect; + InstancePtr->XIsf_Iface_Transfer = XSpi_Transfer; + InstancePtr->XIsf_Iface_Start = XSpi_Start; +#elif XPAR_XISF_INTERFACE_PSSPI + InstancePtr->XIsf_Iface_SetOptions = XSpiPs_SetOptions; + InstancePtr->XIsf_Iface_SetSlaveSelect = XSpiPs_SetSlaveSelect; + InstancePtr->XIsf_Iface_Transfer = XSpiPs_Transfer; + InstancePtr->XIsf_Iface_PolledTransfer = XSpiPs_PolledTransfer; + InstancePtr->XIsf_Iface_SetClkPrescaler = XSpiPs_SetClkPrescaler; +#elif XPAR_XISF_INTERFACE_PSQSPI + InstancePtr->XIsf_Iface_SetOptions = XQspiPs_SetOptions; + InstancePtr->XIsf_Iface_SetSlaveSelect = XQspiPs_SetSlaveSelect; + InstancePtr->XIsf_Iface_Transfer = XQspiPs_Transfer; + InstancePtr->XIsf_Iface_PolledTransfer = XQspiPs_PolledTransfer; + InstancePtr->XIsf_Iface_SetClkPrescaler = XQspiPs_SetClkPrescaler; +#endif +} + + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) +/*****************************************************************************/ +/** +* +* This function initializes the instance structure with the device geometry of +* the Atmel Serial Flash if it is an Atmel device. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferPtr is a pointer to the memory where the device info of +* the Serial Flash is present. +* +* @return - XST_SUCCESS if device information matches the JEDEC +* information of the Atmel Serial Flash. +* - XST_FAILURE if device information doesn't match with Atmel +* Serial Flash. +* +* @note None +* +******************************************************************************/ +static int AtmelFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) +{ + int Status; + u32 Index; + u8 StatusRegister; + u8 NumOfDevices; + u8 ManufacturerID; + + ManufacturerID = BufferPtr[BYTE2]; + if (ManufacturerID == XISF_MANUFACTURER_ID_ATMEL) { + + /* + * For Atmel Serial Flash the device code is the 3rd byte of + * JEDEC info. + */ + InstancePtr->DeviceCode = BufferPtr[BYTE3]; + + /* + * Get the Status Register contents. + * The IsReady is temporarily made TRUE to fetch the Status + * Register contents. + */ + InstancePtr->IsReady = TRUE; + Status = XIsf_GetStatus(InstancePtr, BufferPtr); + InstancePtr->IsReady = FALSE; + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + /* + * Wait until the transfer is complete. + */ + do { +#ifndef XPAR_XISF_INTERFACE_PSQSPI + Status = InstancePtr->XIsf_Iface_SetSlaveSelect( + InstancePtr->SpiInstPtr, + InstancePtr->SpiSlaveSelect); +#else + Status = InstancePtr->XIsf_Iface_SetSlaveSelect( + InstancePtr->SpiInstPtr); +#endif + } while(Status == XST_DEVICE_BUSY); + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + StatusRegister = BufferPtr[BYTE2]; + + /* + * Get the Address mode from the Status Register of Serial + * Flash. + */ + InstancePtr->AddrMode = StatusRegister & + XISF_SR_ADDR_MODE_MASK; + + /* + * Update the Serial Flash instance structure with device + * geometry. + */ + NumOfDevices = sizeof(AtmelDevices) / + sizeof(AtmelDeviceGeometry); + + for(Index = 0; Index < NumOfDevices; Index++) { + if (InstancePtr->DeviceCode == AtmelDevices[Index]. + DeviceCode) { + /* + * Default address mode device. + */ + if (InstancePtr->AddrMode == + XISF_DEFAULT_ADDRESS) { + InstancePtr->BytesPerPage = + AtmelDevices [Index]. + BytesPerPageDefaultMode; + } else { + /* + * Power of 2 address mode device. + */ + InstancePtr->BytesPerPage = + AtmelDevices [Index]. + BytesPerPagePowerOf2Mode; + } + + InstancePtr->PagesPerBlock = + AtmelDevices[Index].PagesPerBlock; + + InstancePtr->BlocksPerSector = + AtmelDevices[Index].BlocksPerSector; + + InstancePtr->NumOfSectors = + AtmelDevices[Index].NumOfSectors; + + if (InstancePtr->BytesPerPage > + XISF_BYTES1024_PER_PAGE ) { + InstancePtr->ByteMask = + XISF_BYTES2048_PER_PAGE_MASK; + } + else if (InstancePtr->BytesPerPage > + XISF_BYTES512_PER_PAGE ) { + InstancePtr->ByteMask = + XISF_BYTES1024_PER_PAGE_MASK; + } + else if (InstancePtr->BytesPerPage > + XISF_BYTES256_PER_PAGE ) { + InstancePtr->ByteMask = + XISF_BYTES512_PER_PAGE_MASK; + } + else { + InstancePtr->ByteMask = + XISF_BYTES256_PER_PAGE_MASK; + } + + InstancePtr->IsReady = TRUE; + } + } + } + + /* + * If the device is not supported, return Failure. + */ + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + return (int)(XST_SUCCESS); +} +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + +#if (((XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) +/*****************************************************************************/ +/** +* +* This function enters the Micron flash device into 4 bytes addressing mode. +* As per the Micron spec, before issuing the command to enter into 4 byte addr +* mode, a write enable command is issued. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return - XST_SUCCESS +* - XST_FAILURE +* +* @note Applicable only for Micron flash devices +* +******************************************************************************/ +int XIsf_MicronFlashEnter4BAddMode(XIsf *InstancePtr) +{ + int Status; + u8* NULLPtr = NULL; + u8 Mode; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->FourByteAddrMode == TRUE) { + return (int)(XST_SUCCESS); + } + + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_ENTER_4BYTE_ADDR_MODE; + + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + NULLPtr, XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES); + + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + InstancePtr->FourByteAddrMode = TRUE; + return Status; +} + +/*****************************************************************************/ +/** +* +* This function exits the Micron flash device from 4 bytes addressing mode. +* As per the Micron spec, before issuing this command a write enable command is +* first issued. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return - XST_SUCCESS +* - XST_FAILURE +* +* @note Applicable only for Micron flash devices +* +******************************************************************************/ +int XIsf_MicronFlashExit4BAddMode(XIsf *InstancePtr) +{ + int Status; + u8* NULLPtr = NULL; + u8 Mode; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->FourByteAddrMode == FALSE) { + return (int)(XST_SUCCESS); + } + + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_EXIT_4BYTE_ADDR_MODE; + + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + NULLPtr, XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES); + + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + InstancePtr->FourByteAddrMode = FALSE; + return Status; +} + +/*****************************************************************************/ +/** +* +* This function initializes the instance structure with the device geometry of +* the Intel/Stm/Winbond Serial Flash if it is an Intel/Stm/Winbond device. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferPtr is a pointer to the memory where the device info of +* the Serial Flash is present. +* +* @return - XST_SUCCESS if device information matches the JEDEC +* information of Intel or Stm or Winbond Serial Flash. +* - XST_FAILURE if device information doesn't match with Intel +* or Stm or Winbond Serial Flash. +* +* @note None +* +******************************************************************************/ +static int IntelStmFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) +{ + u32 Index; + u8 NumOfDevices; + u8 ManufacturerID; + + ManufacturerID = BufferPtr[BYTE2]; + +#if (XPAR_XISF_FLASH_FAMILY == INTEL) + /* + * For Intel the device code is the 4th byte of the JEDEC info. + */ + InstancePtr->DeviceCode = BufferPtr[BYTE4]; +#else + /* + * For STM/Winbond/Spansion Serial Flash the device code is 3rd/4th + * byte of the JEDEC info. The Third Byte is Memory Type and the 4th + * byte represents the capacity. + */ + InstancePtr->DeviceCode = (BufferPtr[BYTE3] << 8) | BufferPtr[BYTE4]; +#endif + + /* + * Check for Intel/STM/Winbond/Spansion Serial Flash. + */ + NumOfDevices = sizeof(IntelStmDevices) / + sizeof(IntelStmDeviceGeometry); + + for(Index = 0; Index < NumOfDevices; Index++) { + if ((InstancePtr->DeviceCode == + IntelStmDevices[Index].DeviceCode) && + (ManufacturerID == + IntelStmDevices[Index].ManufacturerID)) { + InstancePtr->ManufacturerID = IntelStmDevices[Index].ManufacturerID; + InstancePtr->BytesPerPage = + IntelStmDevices[Index].BytesPerPage; + + /* + * This is number of pages per Sector. + */ + InstancePtr->PagesPerBlock = + IntelStmDevices[Index].PagesPerSector; + + InstancePtr->BlocksPerSector = 0; + + InstancePtr->NumOfSectors = + IntelStmDevices[Index].NumOfSectors; + + InstancePtr->IsReady = TRUE; + } + } + + /* + * If the device is not supported, return Failure. + */ + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + return (int)(XST_SUCCESS); +} +#endif /* (((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \ + || (XPAR_XISF_FLASH_FAMILY == SST) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ + +#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI)) +/*****************************************************************************/ +/** +* +* This function initializes the instance structure with the device geometry of +* the Spansion/Micron/Winbond Serial Flash if it is an Spansion/Micron/Winbond +* device. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferPtr is a pointer to the memory where the device info of +* the Serial Flash is present. +* +* @return - XST_SUCCESS if device information matches the JEDEC +* information of Intel or Stm or Winbond Serial Flash. +* - XST_FAILURE if the device information doesn't match with +* Intel or Stm or Winbond Serial Flash. +* +* @note None +* +******************************************************************************/ +static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) +{ + u32 Index; + u8 NumOfDevices; + u8 ManufacturerID; + unsigned int StartIndex; + u32 FlashMake; + u8 * WriteBfrPtr = InstancePtr->WriteBufPtr; + int Status; + + /* + * Read ID in Auto mode. + */ + WriteBfrPtr[BYTE1] = READ_ID; + WriteBfrPtr[BYTE2] = 0x23U; /* 3 dummy bytes */ + WriteBfrPtr[BYTE3] = 0x08U; + WriteBfrPtr[BYTE4] = 0x09U; + + Status = XIsf_Transfer(InstancePtr, WriteBfrPtr, BufferPtr, + RD_ID_SIZE); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + /* + * Deduce flash make + */ + if(BufferPtr[1] == XISF_MANUFACTURER_ID_MICRON) { + FlashMake = XISF_MANUFACTURER_ID_MICRON; + StartIndex = MICRON_INDEX_START; + } + else if(BufferPtr[1] == XISF_MANUFACTURER_ID_SPANSION) { + FlashMake = XISF_MANUFACTURER_ID_SPANSION; + StartIndex = SPANSION_INDEX_START; + } + else if(BufferPtr[1] == XISF_MANUFACTURER_ID_WINBOND) { + FlashMake = XISF_MANUFACTURER_ID_WINBOND; + StartIndex = WINBOND_INDEX_START; + } + else{ + FlashMake = 0; + StartIndex = 0; + } + /* + * If valid flash ID, then check connection mode & size and + * assign corresponding index in the Flash configuration table + */ + if(((FlashMake == XISF_MANUFACTURER_ID_MICRON) || + (FlashMake == XISF_MANUFACTURER_ID_SPANSION)|| + (FlashMake == XISF_MANUFACTURER_ID_WINBOND)) && + (BufferPtr[3] == XISF_MICRON_ID_BYTE2_128)) { + switch(InstancePtr->SpiInstPtr->Config.ConnectionMode) + { + case XISF_QSPIPS_CONNECTION_MODE_SINGLE: + XIsf_FCTIndex = + (u32)FLASH_CFG_TBL_SINGLE_128_SP + + (u32)StartIndex; + break; + case XISF_QSPIPS_CONNECTION_MODE_PARALLEL: + XIsf_FCTIndex = + (u32)FLASH_CFG_TBL_PARALLEL_128_SP + + (u32)StartIndex; + break; + case XISF_QSPIPS_CONNECTION_MODE_STACKED: + XIsf_FCTIndex = + (u32)FLASH_CFG_TBL_STACKED_128_SP + + (u32)StartIndex; + break; + default: + XIsf_FCTIndex = 0; + break; + } + } + + /* + * 256 and 512Mbit supported only for Micron and Spansion, + * not Winbond + */ + if(((FlashMake == XISF_MANUFACTURER_ID_MICRON) || + (FlashMake == XISF_MANUFACTURER_ID_SPANSION)) && + (BufferPtr[3] == XISF_MICRON_ID_BYTE2_256)) { + switch(InstancePtr->SpiInstPtr->Config.ConnectionMode) + { + case XISF_QSPIPS_CONNECTION_MODE_SINGLE: + XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_256_SP + + StartIndex; + break; + case XISF_QSPIPS_CONNECTION_MODE_PARALLEL: + XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_256_SP + + StartIndex; + break; + case XISF_QSPIPS_CONNECTION_MODE_STACKED: + XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_256_SP + + StartIndex; + break; + default: + XIsf_FCTIndex = 0; + break; + } + } + + if(((FlashMake == XISF_MANUFACTURER_ID_MICRON) || + (FlashMake == XISF_MANUFACTURER_ID_SPANSION)) && + (BufferPtr[3] == XISF_MICRON_ID_BYTE2_512)) { + + switch(InstancePtr->SpiInstPtr->Config.ConnectionMode) + { + case XISF_QSPIPS_CONNECTION_MODE_SINGLE: + XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_512_SP + + StartIndex; + break; + case XISF_QSPIPS_CONNECTION_MODE_PARALLEL: + XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_512_SP + + StartIndex; + break; + case XISF_QSPIPS_CONNECTION_MODE_STACKED: + XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_512_SP + + StartIndex; + break; + default: + XIsf_FCTIndex = 0; + break; + } + } + + /* + * 1Gbit Single connection supported for Spansion. + * The ConnectionMode will indicate stacked as this part has 2 SS + * The device ID will indicate 512Mbit. + * This configuration is handled as the above 512Mbit stacked + * configuration. + */ + /* 1Gbit single, parallel and stacked supported for Micron */ + if((FlashMake == XISF_MANUFACTURER_ID_MICRON) && + (BufferPtr[3] == XISF_MICRON_ID_BYTE2_1G)) { + + switch(InstancePtr->SpiInstPtr->Config.ConnectionMode) + { + case XISF_QSPIPS_CONNECTION_MODE_SINGLE: + XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_1GB_MC; + break; + case XISF_QSPIPS_CONNECTION_MODE_PARALLEL: + XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_1GB_MC; + break; + case XISF_QSPIPS_CONNECTION_MODE_STACKED: + XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_1GB_MC; + break; + default: + XIsf_FCTIndex = 0; + break; + } + } + + /* + * Populate the InstancePtr members with the appropriate values + * based on the XIsf_FCTIndex + */ + InstancePtr->BytesPerPage = + (u16)(SpaMicWinDevices[XIsf_FCTIndex].PageSize); + InstancePtr->NumDie = SpaMicWinDevices[XIsf_FCTIndex].NumDie; + InstancePtr->DeviceIDMemSize = + SpaMicWinDevices[XIsf_FCTIndex].DeviceIDMemSize; + InstancePtr->ManufacturerID = FlashMake; + InstancePtr->SectorSize = SpaMicWinDevices[XIsf_FCTIndex].SectSize; + InstancePtr->NumSectors = SpaMicWinDevices[XIsf_FCTIndex].NumSect; + InstancePtr->IsReady = TRUE; + + return (int)(XST_SUCCESS); +} +#endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ + defined(XPAR_XISF_INTERFACE_PSQSPI))*/ + +/*****************************************************************************/ +/** +* This functions translates the address based on the type of interconnection. +* In case of stacked, this function asserts the corresponding slave select. +* +* @param QspiPtr is a pointer to XIsf_Iface instance to be worked on. +* @param Address which is to be accessed (for erase, write or read) +* +* @return RealAddr is the translated address - for single it is unchanged +* for stacked, the lower flash size is subtracted +* for parallel the address is divided by 2. +* +* @note None. +* +******************************************************************************/ +u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address) +{ + u32 LqspiCr; + u32 RealAddr = {0}; +#ifdef XPAR_XISF_INTERFACE_PSQSPI + switch(QspiPtr->Config.ConnectionMode) { + case XISF_QSPIPS_CONNECTION_MODE_SINGLE: + RealAddr = Address; + break; + case XISF_QSPIPS_CONNECTION_MODE_STACKED: + /* + * Get the current LQSPI Config reg value + */ + LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr); + + /* Select lower or upper Flash based on sector address */ + if(Address & + SpaMicWinDevices[XIsf_FCTIndex].FlashDeviceSize) { + /* + * Set selection to U_PAGE + */ + XQspiPs_SetLqspiConfigReg(QspiPtr, + LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK); + + /* + * Subtract first flash size when accessing second + * flash. + */ + RealAddr = Address & + (~SpaMicWinDevices[XIsf_FCTIndex].FlashDeviceSize); + + } + else{ + /* + * Set selection to L_PAGE + */ + XQspiPs_SetLqspiConfigReg(QspiPtr, + LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK)); + + RealAddr = Address; + } + + /* + * Assert the Flash chip select. + */ + (void)XQspiPs_SetSlaveSelect(QspiPtr); + break; + case XISF_QSPIPS_CONNECTION_MODE_PARALLEL: + /* + * The effective address in each flash is the actual + * address / 2 + */ + RealAddr = Address / 2; + break; + default: + /* RealAddr wont be assigned in this case */ + break; + + } +#else + RealAddr = Address; +#endif + return(RealAddr); +} + +#ifdef XPAR_XISF_INTERFACE_PSQSPI +/*****************************************************************************/ +/** +* This functions selects the current bank +* +* @param InstancePtr is a pointer to the QSPI driver component to use. +* @param BankSel is the bank to be selected in the flash device(s). +* +* @return XST_SUCCESS if bank selected, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int SendBankSelect(XIsf *InstancePtr, u32 BankSel) +{ + #define EXTADD_REG_WR 0xC5U + #define EXTADD_REG_RD 0xC8U + #define BANK_REG_WR 0x17U + #define BANK_SEL_SIZE 2U /**< BRWR or EARWR command + + * 1 byte bank value */ + u8 WriteBuffer[5] = {0}; + u8* NULLPtr= NULL; + u8 WriteEnableCmdBuf = { WRITE_ENABLE_CMD }; + u32 FlashMake = InstancePtr->ManufacturerID; + int Status; + /* + * Bank select commands for Micron and Spansion are different + */ + if(FlashMake == XISF_MANUFACTURER_ID_MICRON) { + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * For Micron command WREN should be sent first + * except for some specific feature set + */ + Status = XIsf_Transfer(InstancePtr, + &WriteEnableCmdBuf, NULLPtr, + (u32)sizeof(WriteEnableCmdBuf)); + + if(Status != (int)XST_SUCCESS){ + return (int)XST_FAILURE; + } + + WriteBuffer[BYTE1] = EXTADD_REG_WR; + WriteBuffer[BYTE2] = (u8)BankSel; + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * Send the Extended address register write command + * written, no receive buffer required + */ + Status = XIsf_Transfer(InstancePtr, WriteBuffer, NULLPtr, + BANK_SEL_SIZE); + + if(Status != (int)XST_SUCCESS){ + return (int)XST_FAILURE; + } + } + if(FlashMake == XISF_MANUFACTURER_ID_SPANSION) { + WriteBuffer[BYTE1] = BANK_REG_WR; + WriteBuffer[BYTE2] = (u8)BankSel; + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * Send the Extended address register write command + * written, no receive buffer required + */ + Status = XIsf_Transfer(InstancePtr, WriteBuffer, NULLPtr, + BANK_SEL_SIZE); + + if(Status != (int)XST_SUCCESS){ + return (int)XST_FAILURE; + } + } + + /* Winbond can be added here */ + + return (int)(XST_SUCCESS); +} +#endif + +/****************************************************************************** +* +* This function is to set the Status Handler when an interrupt is registered +* +* @param InstancePtr is a pointer to the XIsf Instance. +* @param QspiInstancePtr is a pointer to the XIsf_Iface instance +* to be worked on. +* @param XilIsf_Handler is the status handler for the application. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XIsf_SetStatusHandler(XIsf *InstancePtr, XIsf_Iface *XIfaceInstancePtr, + XIsf_StatusHandler XilIsf_Handler) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XIfaceInstancePtr != NULL); + Xil_AssertVoid(XilIsf_Handler != NULL); + + /* + * Setup the handler for the QSPI that will be called from the + * interrupt context when an QSPI status occurs, specify a pointer to + * the QSPI driver instance as the callback reference so the handler + * is able to access the instance data + */ +#ifdef XPAR_XISF_INTERFACE_PSQSPI + XQspiPs_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr, + (XQspiPs_StatusHandler) XIsf_IfaceHandler); +#elif XPAR_XISF_INTERFACE_PSSPI + XSpiPs_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr, + (XSpiPs_StatusHandler) XIsf_IfaceHandler); +#elif XPAR_XISF_INTERFACE_AXISPI + XSpi_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr, + (XSpi_StatusHandler) XIsf_IfaceHandler); +#endif + + InstancePtr->StatusHandler = XilIsf_Handler; +} + + + +/****************************************************************************** +* +* This function is the handler which performs processing for the QSPI driver. +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. It is called when a transfer of QSPI data +* completes or an error occurs. +* +* This handler provides an example of how to handle QSPI interrupts but is +* application specific. +* +* @param CallBackRef is a reference passed to the handler. +* @param StatusEvent is the status of the QSPI . +* @param ByteCount is the number of bytes transferred. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XIsf_IfaceHandler(void *CallBackRef, u32 StatusEvent, + unsigned int ByteCount) +{ + + Xil_AssertVoid(CallBackRef != NULL); + + XIsf_TransferInProgress = FALSE; + + XIsf_StatusEventInfo = StatusEvent; + + XIsf_ByteCountInfo = ByteCount; + +} diff --git a/lib/sw_services/xilisf/src/xilisf_erase.c b/lib/sw_services/xilisf/src/xilisf_erase.c new file mode 100644 index 00000000..c2e09970 --- /dev/null +++ b/lib/sw_services/xilisf/src/xilisf_erase.c @@ -0,0 +1,597 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_erase.c +* +* This file contains the library functions to Erase the Serial Flash. +* Refer xilisf.h for a detailed description. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+* 2.01a sdm      01/04/10 Added Support for Winbond W25QXX/W25XX devices
+* 2.04a sdm      08/17/10 Updated to support Numonyx (N25QXX) and Spansion
+*			  flash memories
+* 3.02a srt	 04/25/13 Added Bulk Erase command support for SST and
+*			  Spansion flashes.
+* 5.0   sb	 08/05/14 Updated support for > 128 MB flash for PSQSPI
+*			  interface.
+*			  New API:
+*				DieErase()
+*			  Changed API:
+*				SectorErase()
+*				BulkErase()
+* 5.2  asa       05/12/15 Added support for Micron (N25Q256A) flash part
+* 						  which supports 4 byte addressing.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilisf.h" + +/************************** Constant Definitions *****************************/ +#define SIXTEENMB 0x1000000 /**< Sixteen MB */ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr, + u32 ByteCount); +extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address); +#ifdef XPAR_XISF_INTERFACE_PSQSPI +extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel); +#endif +static int PageErase(XIsf *InstancePtr, u32 Address); +static int BlockErase(XIsf *InstancePtr, u32 Address); +static int SectorErase(XIsf *InstancePtr, u32 Address); +static int BulkErase(XIsf *InstancePtr); +#ifdef XPAR_XISF_INTERFACE_PSQSPI +static int DieErase(XIsf *InstancePtr); +#endif +/************************** Variable Definitions *****************************/ +extern u32 XIsf_StatusEventInfo; +extern unsigned int XIsf_ByteCountInfo; +/************************** Function Definitions ******************************/ + + +/*****************************************************************************/ +/** +* +* This API erases the contents of the specified memory in the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Operation is the type of Erase operation to be performed on the +* Serial Flash. +* The different operations are +* - XISF_PAGE_ERASE: Page Erase +* - XISF_BLOCK_ERASE: Block Erase +* - XISF_SECTOR_ERASE: Sector Erase + - XISF_BULK_ERASE: Bulk Erase +* @param Address is the address of the Page/Block/Sector to be erased. +* The address can be either Page address, Block address or Sector +* address based on the Erase operation to be performed. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - The erased bytes will read as 0xFF. +* - For Intel, STM, Winbond or Spansion Serial Flash the user +* application must call XIsf_WriteEnable() API by passing +* XISF_WRITE_ENABLE as an argument before calling XIsf_Erase() +* API. +* - Atmel Serial Flash support Page/Block/Sector Erase + - operations. +* - Intel, Winbond, Numonyx (N25QXX) and Spansion Serial Flash +* support Sector/Block/Bulk Erase operations. +* - STM (M25PXX) Serial Flash support Sector/Bulk Erase +* operations. +* +******************************************************************************/ +int XIsf_Erase(XIsf *InstancePtr, XIsf_EraseOperation Operation, u32 Address) +{ + int Status = (int)(XST_FAILURE); + u8 Mode; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + switch (Operation) { + + case XISF_PAGE_ERASE: + Status = PageErase(InstancePtr, Address); + break; + + case XISF_BLOCK_ERASE: + Status = BlockErase(InstancePtr, Address); + break; + + case XISF_SECTOR_ERASE: + Status = SectorErase(InstancePtr, Address); + break; + + case XISF_BULK_ERASE: + Status = BulkErase(InstancePtr); + break; + + default: + break; + } + + + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + return Status; +} + + +/*****************************************************************************/ +/** +* +* This function erases the contents of the specified Page in the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the address of Page to be erased. This can be any +* address in the Page to be erased. The Byte address values in +* this address are ignored. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - The erased bytes will read as 0xFF. +* - This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int PageErase(XIsf *InstancePtr, u32 Address) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Address != 0); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PAGE_ERASE; + InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + NULL, XISF_CMD_SEND_EXTRA_BYTES); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function erases the contents of the specified Block in the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the address of the Block to be erased. This can be +* any address in the Block to be erased. The Page/Byte address +* values in this address are ignored. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - The erased bytes will read as 0xFF. +* - This operation is supported for Atmel, Intel, Winbond, +* Numonyx (N25QXX), and Spansion Serial Flash. +* +******************************************************************************/ +static int BlockErase(XIsf *InstancePtr, u32 Address) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Address != 0); + +#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == INTEL) \ + || (XPAR_XISF_FLASH_FAMILY == WINBOND)) + +#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == WINBOND)) + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BLOCK_ERASE; + +#else + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PARAM_BLOCK_ERASE; + +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + NULL, XISF_CMD_SEND_EXTRA_BYTES); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* ((XPAR_XISF_FLASH_FAMILY==ATMEL)||(XPAR_XISF_FLASH_FAMILY==INTEL)) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function erases the contents of the specified Sector in Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the address of the Sector to be erased. This can be +* any address in the Sector to be erased. +* The Block/Page/Byte address values in this address are ignored. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - The erased bytes will read as 0xFF. +* - This operation is supported for Atmel, Intel, STM, Winbond +* and Spansion Serial Flash. +* +******************************************************************************/ +static int SectorErase(XIsf *InstancePtr, u32 Address) +{ + int Status = (int)(XST_FAILURE); + u8 Mode; + u32 BankSel; + u32 RealAddr; + u8* NULLPtr = NULL; + u8 FlagStatus[2] = {0}; + u8 FlashStatus[2] = {0}; + u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 }; + u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0}; +#ifdef XPAR_XISF_INTERFACE_PSQSPI + u32 FlashMake = InstancePtr->ManufacturerID; +#endif + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * Translate address based on type of connection + * If stacked assert the slave select based on address + */ + RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address); + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + /* + * Initial bank selection + */ + if(InstancePtr->DeviceIDMemSize > 0x18U) { + + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + /* + * Seting the transfer mode to Polled Mode before + * performing the Bank Select operation. + */ + XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE); + + /* + * Calculate initial bank + */ + BankSel = RealAddr/SIXTEENMB; + /* + * Select bank + */ + Status = SendBankSelect(InstancePtr, BankSel); + + /* + * Restoring the transfer mode back + */ + XIsf_SetTransferMode(InstancePtr, Mode); + + if(Status!=(int)(XST_SUCCESS)){ + return (int)XST_FAILURE; + } + } +#endif +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + if (InstancePtr->FourByteAddrMode == TRUE) { + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE; + InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr); + } else { +#endif + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE; + InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr); +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + } +#endif + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + /* + * Enable write before transfer + */ + Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif + if (InstancePtr->FourByteAddrMode == TRUE) { + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + NULLPtr, XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE); + } else { + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + NULLPtr, XISF_CMD_SEND_EXTRA_BYTES); + } + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + if((InstancePtr->NumDie > (u8)1) && + (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { + + Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, + (u32)sizeof(ReadFlagSRCmd)); + } + + /* + * Wait for the sector erase command to the Flash to be completed + */ + while (1) { + /* + * Poll the status register of the device to determine + * when it completes, by sending a read status command + * and receiving the status byte + */ + Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf, + FlashStatus, + (u32)sizeof(ReadStatusCmdBuf)); + + /* + * If the status indicates the write is done, then stop + * waiting, if a value of 0xFF in the status byte is + * read from the device and this loop never exits, the + * device slave select is possibly incorrect such that + * the device status is not being read + */ + if ((FlashStatus[1] & 0x01) == 0) { + break; + } + } + + if((InstancePtr->NumDie > (u8)1) && + (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { + + Status = + XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, + (u32)sizeof(ReadFlagSRCmd)); + } +#endif + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function erases the content of an entire Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - The erased bytes will read as 0xFF. +* - This operation is supported for Intel, STM, Winbond, +* Spansion and SST Serial Flashes. +* +******************************************************************************/ +static int BulkErase(XIsf *InstancePtr) +{ + int Status = (int)(XST_FAILURE); + u8* NULLPtr = NULL; + +#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST) \ + || (XPAR_XISF_FLASH_FAMILY == SPANSION)) + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + /* + * If the number of die is greater than 1 call die erase + */ + if(InstancePtr->NumDie > 1){ + Status = DieErase(InstancePtr); + } + + else{ +#endif + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BULK_ERASE; + + /* + * Enable write before transfer + */ + Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, + NULLPtr, XISF_BULK_ERASE_BYTES); +#ifdef XPAR_XISF_INTERFACE_PSQSPI + } +#endif +#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY==STM)) \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || + (XPAR_XISF_FLASH_FAMILY == SST) || + (XPAR_XISF_FLASH_FAMILY == SPANSION)) */ + + return Status; +} + +#ifdef XPAR_XISF_INTERFACE_PSQSPI +/*****************************************************************************/ +/** +* +* This function erases the content of a Die of Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - This operation is supported for Winbond, +* Spansion and Micron Serial Flashes. +* +******************************************************************************/ +static int DieErase(XIsf *InstancePtr) +{ + int Status = (int)(XST_FAILURE); + u8* NULLPtr = NULL; +#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) + + u8 DieCnt; + u8 ReadFlagSRCmd[] = { READ_FLAG_STATUS_CMD, 0 }; + u8 FlagStatus[2] = {0}; + + for(DieCnt = 0; DieCnt < InstancePtr->NumDie; DieCnt++) { + /* + * Select bank - the lower of the 2 banks in each die + * This is specific to Micron flash + */ + Status = SendBankSelect(InstancePtr, DieCnt*2); + + /* + * Setup the write command with the specified address and data + * for the Flash + */ + /* + * This ensures 3B address is sent to flash even with address + * greater than 128Mb. + * The address is the start address of die - MSB bits will be + * derived from bank select by the flash + */ + InstancePtr->WriteBufPtr[BYTE1] = DIE_ERASE_CMD; + InstancePtr->WriteBufPtr[BYTE2] = 0x00; + InstancePtr->WriteBufPtr[BYTE3] = 0x00; + InstancePtr->WriteBufPtr[BYTE4] = 0x00; + + /* + * Enable write before transfer + */ + Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } + + Xil_AssertNonvoid(NULLPtr == NULL); + + /* + * Send the sector erase command and address; no receive buffer + * is specified since there is nothing to receive + */ + Status = + XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, + DIE_ERASE_SIZE); + + /* + * Wait for the sector erase command to Flash to be completed + */ + while (1) { + + /* + * Poll the status register of the device to determine + * when it completes, by sending a read status command + * and receiving the status byte + */ + Status = + XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, + (u32)sizeof(ReadFlagSRCmd)); + + /* + * If the status indicates the write is done, then stop + * waiting, if a value of 0xFF in the status byte is + * read from the device and this loop never exits, the + * device slave select is possibly incorrect such that + * the device status is not being read + */ + if ((FlagStatus[1] & (u8)0x80) == (u8)0x80) { + break; + } + } + + } + +#endif /* ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION)) */ + + return Status; +} +#endif diff --git a/lib/sw_services/xilisf/src/xilisf_read.c b/lib/sw_services/xilisf/src/xilisf_read.c new file mode 100644 index 00000000..ae999aee --- /dev/null +++ b/lib/sw_services/xilisf/src/xilisf_read.c @@ -0,0 +1,978 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_read.c +* +* This file contains the library functions to read data from the Serial Flash +* devices. Refer xilisf.h for detailed description. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+* 2.01a sdm      01/04/10 Added Support for Winbond W25QXX/W25XX devices
+* 2.04a sdm      08/17/10 Updated to support Numonyx (N25QXX) and Spansion
+*			  flash memories
+* 5.0   sb	 08/05/14 Updated support for > 128 MB flash for PSQSPI
+*			  interface.
+*			  Changed API:
+*				ReadData()
+*				FastReadData()
+*
+* 5.2  asa       05/12/15 Added support for Micron (N25Q256A) flash part
+* 						  which supports 4 byte addressing.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilisf.h" + +/************************** Constant Definitions *****************************/ + +#define FAST_READ_NUM_DUMMY_BYTES 1 +#define SIXTEENMB 0x1000000 /**< Sixteen MB */ +#define BANKMASK 0xF000000 /**< Bank mask */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr, + u32 ByteCount); +extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address); + +#ifdef XPAR_XISF_INTERFACE_PSQSPI +extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel); +#endif + +static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, + u32 ByteCount); +static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, + u8 *ReadPtr, + u32 ByteCount, int NumDummyBytes); +static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address); +static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr, + u32 ByteOffset, u32 NumBytes); +static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr, + u32 ByteOffset, u32 NumBytes); +static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, + u32 ByteCount); + +/************************** Variable Definitions *****************************/ +extern u32 XIsf_StatusEventInfo; +extern unsigned int XIsf_ByteCountInfo; +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* This API reads the data from the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Operation is the type of the read operation to be performed on +* the Serial Flash. +* The different operations are + - XISF_READ: Normal Read +* - XISF_FAST_READ: Fast Read +* - XISF_PAGE_TO_BUF_TRANS: Page to Buffer Transfer +* - XISF_BUFFER_READ: Buffer Read +* - XISF_FAST_BUFFER_READ: Fast Buffer Read +* - XISF_OTP_READ: One Time Programmable Area (OTP) Read +* - XISF_DUAL_OP_FAST_READ: Dual Output Fast Read +* - XISF_DUAL_IO_FAST_READ: Dual Input/Output Fast Read +* - XISF_QUAD_OP_FAST_READ: Quad Output Fast Read +* - XISF_QUAD_IO_FAST_READ: Quad Input/Output Fast Read +* @param OpParamPtr is the pointer to structure variable which contains +* operational parameter of specified Operation. This parameter +* type is dependant on the type of Operation to be performed. +* +* - Normal Read (XISF_READ), Fast Read (XISF_FAST_READ), +* One Time Programmable Area Read(XISF_OTP_READ), Dual Output +* Fast Read (XISF_CMD_DUAL_OP_FAST_READ), Dual Input/Output +* Fast Read (XISF_CMD_DUAL_IO_FAST_READ), Quad Output Fast Read +* (XISF_CMD_QUAD_OP_FAST_READ) and Quad Input/Output Fast Read +* (XISF_CMD_QUAD_IO_FAST_READ): +* The OpParamPtr must be of type struct XIsf_ReadParam. +* OpParamPtr->Address is start address in the Serial Flash. +* OpParamPtr->ReadPtr is a pointer to the memory where the data +* read from the Serial Flash is stored. +* OpParamPtr->NumBytes is number of bytes to read. +* OpParamPtr->NumDummyBytes is the number of dummy bytes to be +* transmitted for the Read command. This parameter is only used +* in case of Dual and Quad reads. +* Normal Read and Fast Read operations are supported for Atmel, +* Intel, STM, Winbond and Spansion Serial Flash. +* Dual and quad reads are supported for Winbond (W25QXX), Numonyx +* (N25QXX) and Spansion (S25FL129) quad flash. +* OTP Read operation is only supported in Intel Serial Flash. +* +* - Page To Buffer Transfer (XISF_PAGE_TO_BUF_TRANS): +* The OpParamPtr must be of type struct +* XIsf_FlashToBufTransferParam . +* OpParamPtr->BufferNum specifies the internal SRAM Buffer of +* the Serial Flash. The valid values are XISF_PAGE_BUFFER1 +* or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case +* of AT45DB011D Flash as it contains a single buffer. +* OpParamPtr->Address is start address in the Serial Flash. +* This operation is only supported in Atmel Serial Flash. +* +* - Buffer Read (XISF_BUFFER_READ) and Fast Buffer Read +* (XISF_FAST_BUFFER_READ): +* The OpParamPtr must be of type struct XIsf_BufferReadParam. +* OpParamPtr->BufferNum specifies the internal SRAM Buffer of +* the Serial Flash. The valid values are XISF_PAGE_BUFFER1 +* or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of +* AT45DB011D Flash as it contains a single buffer. +* OpParamPtr->ReadPtr is pointer to the memory where data read +* from the SRAM buffer is to be stored. +* OpParamPtr->ByteOffset is byte offset in the SRAM buffer from +* where the first byte is read. +* OpParamPtr->NumBytes is the number of bytes to be read from the +* Buffer. +* These operations are supported only in Atmel Serial Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - Application must fill the structure elements of the third +* argument and pass its pointer by type casting it with void +* pointer. +* - The valid data is available from the fourth location pointed +* to by the ReadPtr for Normal Read and Buffer Read operations. +* - The valid data is available from fifth location pointed to +* by the ReadPtr for Fast Read, Fast Buffer Read and OTP Read +* operations. +* - The valid data is available from the (4 + NumDummyBytes)th +* location pointed to by ReadPtr for Dual/Quad Read operations. +* +******************************************************************************/ +int XIsf_Read(XIsf *InstancePtr, XIsf_ReadOperation Operation, + void *OpParamPtr) +{ + int Status = (int)(XST_FAILURE); + u8 Mode; + XIsf_ReadParam *ReadParamPtr; + XIsf_FlashToBufTransferParam *FlashToBufTransferParamPtr; + XIsf_BufferReadParam *BufferReadParamPtr; + + if (InstancePtr == NULL) { + return (int)(XST_FAILURE); + } + + if (InstancePtr->IsReady != TRUE) { + return (int)(XST_FAILURE); + } + + if (NULL == OpParamPtr) { + return (int)(XST_FAILURE); + } + + switch (Operation) { + case XISF_READ: + ReadParamPtr = (XIsf_ReadParam*) OpParamPtr; + Status = ReadData(InstancePtr, + ReadParamPtr->Address, + ReadParamPtr->ReadPtr, + ReadParamPtr->NumBytes); + break; + + case XISF_FAST_READ: + ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(ReadParamPtr != NULL); + Status = FastReadData(InstancePtr, + XISF_CMD_FAST_READ, + ReadParamPtr->Address, + ReadParamPtr->ReadPtr, + ReadParamPtr->NumBytes, + ReadParamPtr->NumDummyBytes); + break; + + case XISF_PAGE_TO_BUF_TRANS: + FlashToBufTransferParamPtr = + (XIsf_FlashToBufTransferParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(FlashToBufTransferParamPtr != NULL); + Status = FlashToBufTransfer(InstancePtr, + FlashToBufTransferParamPtr->BufferNum, + FlashToBufTransferParamPtr->Address); + break; + + case XISF_BUFFER_READ: + BufferReadParamPtr = + (XIsf_BufferReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(BufferReadParamPtr != NULL); + Status = BufferRead(InstancePtr, + BufferReadParamPtr->BufferNum, + BufferReadParamPtr->ReadPtr, + BufferReadParamPtr->ByteOffset, + BufferReadParamPtr->NumBytes); + break; + + case XISF_FAST_BUFFER_READ: + BufferReadParamPtr = + (XIsf_BufferReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(BufferReadParamPtr != NULL); + Status = FastBufferRead(InstancePtr, + BufferReadParamPtr->BufferNum, + BufferReadParamPtr->ReadPtr, + BufferReadParamPtr->ByteOffset, + BufferReadParamPtr->NumBytes); + break; + + case XISF_OTP_READ: + ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(ReadParamPtr != NULL); + Status = ReadOTPData(InstancePtr, + ReadParamPtr->Address, + ReadParamPtr->ReadPtr, + ReadParamPtr->NumBytes); + break; + +#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \ + || (XPAR_XISF_FLASH_FAMILY == SPANSION)) + case XISF_DUAL_OP_FAST_READ: + ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(ReadParamPtr != NULL); + Status = FastReadData(InstancePtr, + XISF_CMD_DUAL_OP_FAST_READ, + ReadParamPtr->Address, + ReadParamPtr->ReadPtr, + ReadParamPtr->NumBytes, + ReadParamPtr->NumDummyBytes); + break; + + case XISF_DUAL_IO_FAST_READ: + ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(ReadParamPtr != NULL); + Status = FastReadData(InstancePtr, + XISF_CMD_DUAL_IO_FAST_READ, + ReadParamPtr->Address, + ReadParamPtr->ReadPtr, + ReadParamPtr->NumBytes, + ReadParamPtr->NumDummyBytes); + break; + + case XISF_QUAD_OP_FAST_READ: + ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(ReadParamPtr != NULL); + Status = FastReadData(InstancePtr, + XISF_CMD_QUAD_OP_FAST_READ, + ReadParamPtr->Address, + ReadParamPtr->ReadPtr, + ReadParamPtr->NumBytes, + ReadParamPtr->NumDummyBytes); + break; + + case XISF_QUAD_IO_FAST_READ: + ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(ReadParamPtr != NULL); + Status = FastReadData(InstancePtr, + XISF_CMD_QUAD_IO_FAST_READ, + ReadParamPtr->Address, + ReadParamPtr->ReadPtr, + ReadParamPtr->NumBytes, + ReadParamPtr->NumDummyBytes); + break; +#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) || + (XPAR_XISF_FLASH_FAMILY == STM) || + (XPAR_XISF_FLASH_FAMILY == SPANSION))*/ + + default: + break; + } + + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function reads data from the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the starting address in the Serial Flash from where +* the data is to be read. +* @param ReadPtr is a pointer to the memory where the data read from +* the Serial Flash is stored. +* @param ByteCount is the number of bytes to be read from the Serial +* Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - This operation is supported for Atmel, Intel, STM, Winbond +* and Spansion Serial Flash. +* - Minimum of one byte and a maximum of an entire Serial Flash +* Array can be read. +* - The valid data is available from the fourth location pointed +* to by the ReadPtr. +* +******************************************************************************/ +static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount) +{ + u8 Mode; + u32 BankSel; + u32 RealAddr; + int Status; + u32 RealByteCnt; + u32 BufferIndex; + u8 ShiftSize; + u32 TotalByteCnt = ByteCount; + u32 LocalByteCnt = ByteCount; + u32 LocalAddress = Address; + u8 WriteBuffer[10] = {0}; + if (LocalByteCnt <= 0 ) { + return (int)XST_FAILURE; + } + + if (ReadPtr == NULL) { + return (int)XST_FAILURE; + } + + while(((s32)(LocalByteCnt)) > 0) { + + /* + * Translate address based on type of connection + * If stacked assert the slave select based on address + */ + RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress); + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + if(InstancePtr->DeviceIDMemSize > 0x18U) { + + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + /* + * Seting the transfer mode to Polled Mode before + * performing the Bank Select operation. + */ + XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE); + + BankSel = RealAddr/SIXTEENMB; + + (void)SendBankSelect(InstancePtr, BankSel); + + /* + * Restoring the transfer mode back + */ + XIsf_SetTransferMode(InstancePtr, Mode); + } + + /* + * If data to be read spans beyond the current bank, then + * calculate RealByteCnt in current bank. Else + * RealByteCnt is the same as ByteCount + */ + if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) { + RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr; + } + else { +#endif + RealByteCnt = LocalByteCnt; + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + } +#endif +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + if (InstancePtr->FourByteAddrMode == TRUE) { + WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ_4BYTE; + WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24); + WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); + WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); + WriteBuffer[BYTE5] = (u8) (RealAddr); + } else { +#endif + WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ; + WriteBuffer[BYTE2] = (u8)((RealAddr & 0xFF0000) >> XISF_ADDR_SHIFT16); + WriteBuffer[BYTE3] = (u8)((RealAddr & 0xFF00) >> XISF_ADDR_SHIFT8); + WriteBuffer[BYTE4] = (u8)(RealAddr & 0xFF); +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + } +#endif + if (InstancePtr->FourByteAddrMode == TRUE) { + Status = XIsf_Transfer(InstancePtr, WriteBuffer, + &(ReadPtr[TotalByteCnt - LocalByteCnt]), + RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE); + } else { + Status = XIsf_Transfer(InstancePtr, WriteBuffer, + &(ReadPtr[TotalByteCnt - LocalByteCnt]), + RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES); + } + if (Status != (int)(XST_SUCCESS)) { + return (int)XST_FAILURE; + } + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + /* + * To discard the first 4 dummy bytes, shift the data in read buffer + */ + ShiftSize = XISF_CMD_SEND_EXTRA_BYTES; + BufferIndex = (TotalByteCnt - LocalByteCnt); + for(; + BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt); + BufferIndex++) { + ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize]; + } + + /* + * Increase address to next bank + */ + LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB; +#endif + /* + * Decrease byte count by bytes already read. + */ + LocalByteCnt = LocalByteCnt - RealByteCnt; + + } + + return (int)XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function reads data from the Serial Flash at a higher speed than normal +* Read operation. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Command is the fast read command used to read data from the +* flash. It could be one of XISF_CMD_DUAL/QUAD_*_FAST_READ or +* XISF_CMD_FAST_READ. +* @param Address is the starting address in the Serial Flash from where +* the data is to be read. +* @param ReadPtr is a pointer to the memory where the data read from +* the Serial Flash is stored. +* @param ByteCount is the number of bytes to be read from the Serial +* Flash. +* @param NumDummyBytes is the number of dummy bytes associated with the +* fast read commands. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - XISF_CMD_FAST_READ operation is supported for Atmel, Intel, +* STM, Winbond and Spansion Serial Flash. +* - XISF_CMD_DUAL/QUAD_*_FAST_READ operations are supported on +* Winbond (W25QXX), Numonyx (N25QXX) and Spansion (S25FL129) +* quad flash devices. +* - Minimum of one byte and a maximum of an entire Serial Flash +* Array can be read. +* - The valid data is available from the (4 + NumDummyBytes)th +* location pointed to by the ReadPtr. +* +******************************************************************************/ +static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, + u8 *ReadPtr, u32 ByteCount, int NumDummyBytes) +{ + u8 Mode; + int Index; + int Status; + u32 BankSel; + u32 RealAddr; + u32 RealByteCnt; + u32 BufferIndex; + u8 ShiftSize; + u32 TotalByteCnt = ByteCount; + u32 LocalByteCnt = ByteCount; + u32 LocalAddress = Address; + u8 WriteBuffer[5]= {0}; + + if (LocalByteCnt <= 0 ) { + return (int)XST_FAILURE; + } + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + + if (NumDummyBytes <= 0) { + return (int)(XST_FAILURE); + } + + while(((s32)(LocalByteCnt)) > 0) { + + /* + * Translate address based on type of connection + * If stacked assert the slave select based on address + */ + RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress); + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + if(InstancePtr->DeviceIDMemSize > 0x18U) { + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + /* + * Seting the transfer mode to Polled Mode before + * performing the Bank Select operation. + */ + XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE); + + BankSel = RealAddr/SIXTEENMB; + + (void)SendBankSelect(InstancePtr, BankSel); + + /* + * Restoring the transfer mode back + */ + XIsf_SetTransferMode(InstancePtr, Mode); + } + + /* + * If data to be read spans beyond the current bank, then + * calculate RealByteCnt in current bank. Else + * RealByteCnt is the same as ByteCount + */ + if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) { + RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr; + } + else { +#endif + RealByteCnt = LocalByteCnt; + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + } +#endif +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + if (InstancePtr->FourByteAddrMode == TRUE) { + WriteBuffer[BYTE1] = Command; + WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24); + WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); + WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); + WriteBuffer[BYTE5] = (u8) RealAddr; + + for (Index = 0; Index < NumDummyBytes; Index++) { + WriteBuffer[Index + BYTE5 + 1] = (u8) (XISF_DUMMYBYTE); + } + } else { +#endif + WriteBuffer[BYTE1] = Command; + WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); + WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); + WriteBuffer[BYTE4] = (u8) RealAddr; + + for (Index = 0; Index < NumDummyBytes; Index++) { + WriteBuffer[Index + BYTE5] = (u8) (XISF_DUMMYBYTE); + } +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + } +#endif + RealByteCnt += NumDummyBytes; + if (InstancePtr->FourByteAddrMode == TRUE) { + Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer, + &(ReadPtr[TotalByteCnt - LocalByteCnt]), + RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE); + } else { + Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer, + &(ReadPtr[TotalByteCnt - LocalByteCnt]), + RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES); + } + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + /* + * To discard the first 5 dummy bytes, shift the data in read buffer + */ + ShiftSize = XISF_CMD_SEND_EXTRA_BYTES + (u8)NumDummyBytes; + BufferIndex = (TotalByteCnt - LocalByteCnt); + for(; + BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt); + BufferIndex++) { + ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize]; + } + + /* + * Increase address to next bank + */ + LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB; +#endif + /* + * Decrease byte count by bytes already read. + */ + LocalByteCnt = LocalByteCnt - (RealByteCnt - NumDummyBytes); + } + + return (int)XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function copies the data from the Serial Flash to the specified SRAM +* buffer. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferNum specifies the internal SRAM Buffer to which the data +* from Serial Flash is to be transferred. The valid values are +* XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is +* not valid in the case of AT45DB011D Flash as it contains a +* single buffer. +* @param Address specifies any address within the Page of the Serial +* Flash from where the Page of data is to be copied. +* Byte address in this Address is ignored as an entire Page of +* data is transferred/copied. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - This operation is only supported in Atmel Serial Flash. +* - This function reads one complete Page from the Serial Flash. +* - Read the Spartan-3AN In-system Flash User Guide/Atmel +* AT45XXXD Data sheets for more information. +* +******************************************************************************/ +static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Address != 0); + Xil_AssertNonvoid(BufferNum != 0); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Check whether the buffer number is valid or not. + */ + if ((BufferNum == XISF_PAGE_BUFFER1) || + (BufferNum == XISF_PAGE_BUFFER2)) { + if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) && + (BufferNum != XISF_PAGE_BUFFER1)) { + return (int)(XST_FAILURE); + } + } else { + return (int)(XST_FAILURE); + } + + if (BufferNum == XISF_PAGE_BUFFER1) { + /* + * Page to Buffer 1 Transfer. + */ + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_PAGETOBUF1_TRANS; + } else { + /* + * Page to Buffer 2 Transfer. + */ + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_PAGETOBUF2_TRANS; + } + + InstancePtr->WriteBufPtr[BYTE2] = (u8)(Address >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8)(Address >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8)(XISF_DUMMYBYTE); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_CMD_SEND_EXTRA_BYTES); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; + +} + +/*****************************************************************************/ +/** +* +* This function reads the data available in the SRAM buffer of Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferNum specifies the internal SRAM Buffer from which data +* is to be read. The valid values are XISF_PAGE_BUFFER1 or +* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of +* AT45DB011D Flash as it contains a single buffer. +* @param ReadPtr is a pointer to the memory where the data read from the +* SRAM buffer is stored. +* @param ByteOffset is the byte offset in the buffer from where the +* first byte is read. +* @param NumBytes is the number of bytes to be read from the Buffer. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - This operation is only supported in Atmel Serial Flash. +* - This function reads a Minimum of one Byte and a Maximum of an +* entire SRAM buffer (1 Page) from the Serial Flash. +* - The valid data is available from the fourth location pointed +* to by the ReadPtr. +* - Read the Spartan-3AN In-system Flash User Guide/Atmel +* AT45XXXD Data sheets for more information. +* +******************************************************************************/ +static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr, + u32 ByteOffset, u32 NumBytes) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferNum != 0); + Xil_AssertNonvoid(ReadPtr != NULL); + Xil_AssertNonvoid(ByteOffset != 0); + Xil_AssertNonvoid(NumBytes != 0); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + + /* + * Check if the buffer number is valid or not. + */ + if ((BufferNum == XISF_PAGE_BUFFER1) || + (BufferNum == XISF_PAGE_BUFFER2)) { + if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) && + (BufferNum != XISF_PAGE_BUFFER1)) { + return (int)(XST_FAILURE); + } + } else { + return (int)(XST_FAILURE); + } + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + + if (ByteOffset > InstancePtr->BytesPerPage){ + return (int)(XST_FAILURE); + } + + if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) { + return (int)(XST_FAILURE); + } + + if (BufferNum == XISF_PAGE_BUFFER1) { + ReadPtr[BYTE1] = XISF_CMD_BUF1_READ; /* Buffer 1 Read. */ + } else { + ReadPtr[BYTE1] = XISF_CMD_BUF2_READ; /* Buffer 2 Read.*/ + } + ReadPtr[BYTE2] = (u8) (0x00); + ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8); + ReadPtr[BYTE4] = (u8) ByteOffset; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr, + NumBytes + XISF_CMD_SEND_EXTRA_BYTES); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; + +} +/*****************************************************************************/ +/** +* +* This function reads the data from the internal SRAM page buffer of the Serial +* Flash memory at higher speed than normal Buffer Read operation. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferNum specifies the internal SRAM Buffer from which data +* is to be read. The valid values are XISF_PAGE_BUFFER1 or +* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of +* AT45DB011D Flash as it contains a single buffer. +* @param ReadPtr is a pointer to the memory where the data read from the +* SRAM buffer is stored. +* @param ByteOffset is the byte offset in the buffer from where the +* first byte is read. +* @param NumBytes is the number of bytes to be read from the Buffer. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - This operation is only supported in Atmel Serial Flash. +* - This function reads a Minimum of one Byte and a Maximum of an +* entire SRAM buffer (1 Page) from the Serial Flash. +* - The valid data is available from the fifth location pointed +* to by the ReadPtr. +* - Read the Spartan-3AN In-system Flash User Guide/Atmel +* AT45XXXD Data sheets for more information. +* +******************************************************************************/ +static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr, + u32 ByteOffset, u32 NumBytes) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferNum != 0); + Xil_AssertNonvoid(ReadPtr != NULL); + Xil_AssertNonvoid(ByteOffset != 0); + Xil_AssertNonvoid(NumBytes != 0); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Check if the buffer number is valid or not. + */ + if ((BufferNum == XISF_PAGE_BUFFER1) || + (BufferNum == XISF_PAGE_BUFFER2)) { + if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) && + (BufferNum != XISF_PAGE_BUFFER1)) { + return (int)(XST_FAILURE); + } + } else { + return (int)(XST_FAILURE); + } + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + + if (ByteOffset > InstancePtr->BytesPerPage){ + return (int)(XST_FAILURE); + } + + if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) { + return (int)(XST_FAILURE); + } + + if (BufferNum == XISF_PAGE_BUFFER1) { + /* + * Buffer 1 Fast Read. + */ + ReadPtr[BYTE1] = XISF_CMD_FAST_BUF1_READ; + } else { + /* + * Buffer 2 Fast Read. + */ + ReadPtr[BYTE1] = XISF_CMD_FAST_BUF2_READ; + } + + ReadPtr[BYTE2] = (u8) (0x00); + ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8); + ReadPtr[BYTE4] = (u8) ByteOffset; + ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr, + NumBytes + XISF_CMD_FAST_READ_EXTRA_BYTES); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function reads the data from OTP area of the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the starting address in OTP area of the Serial Flash +* from which the data is to be read. +* @param ReadPtr is a pointer to the memory where the data read from the +* Serial Flash is stored. +* @param ByteCount is the number of bytes to be read from the Serial +* Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - This operation is only supported for Intel Serial Flash. +* - Minimum of one byte and a maximum of an entire Serial Flash +* array can be read. +******************************************************************************/ +static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, + u32 ByteCount) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Address != 0); + Xil_AssertNonvoid(ReadPtr != NULL); + Xil_AssertNonvoid(ByteCount != 0); + +#if (XPAR_XISF_FLASH_FAMILY == INTEL) + if (ByteCount <= 0 ) { + return (int)(XST_FAILURE); + } + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + + ReadPtr[BYTE1] = XISF_CMD_OTP_READ; + ReadPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16); + ReadPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8); + ReadPtr[BYTE4] = (u8) Address; + ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE); + + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr, + ByteCount + XISF_OTP_RDWR_EXTRA_BYTES); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */ + + return Status; +} diff --git a/lib/sw_services/xilisf/src/xilisf_spr.c b/lib/sw_services/xilisf/src/xilisf_spr.c new file mode 100644 index 00000000..50c173db --- /dev/null +++ b/lib/sw_services/xilisf/src/xilisf_spr.c @@ -0,0 +1,411 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_spr.c +* +* This file contains the library functions to operate on Sector Protection +* feature of the Serial Flash. Refer xilisf.h for a detailed description. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+* 2.01a sdm      01/04/10 Added Support for Winbond W25QXX/W25XX devices
+* 2.04a sdm      08/17/10 Updated to support Numonyx (N25QXX) and Spansion
+*			  flash memories
+* 5.0   sb	 08/05/14 Added Call back to lib interrupt handler
+*			  after XIsf_Transfer Calls.
+*			  Changed API:
+*			  - XIsf_SectorProtect()
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilisf.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr, + u32 ByteCount); +extern int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr); +static int SprRead(XIsf *InstancePtr, u8 *ReadPtr); +static int SprProgram(XIsf *InstancePtr, u8 *BufferPtr); + +static int SprErase(XIsf *InstancePtr); +static int SpEnable(XIsf *InstancePtr); +static int SpDisable(XIsf *InstancePtr); + +/************************** Variable Definitions *****************************/ +extern u32 XIsf_StatusEventInfo; +extern unsigned int XIsf_ByteCountInfo; +/************************** Function Definitions ******************************/ + + +/*****************************************************************************/ +/** +* +* This API is used for performing Sector Protect related operations. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Operation is the type of Sector Protect operation to be +* performed on the Serial Flash. +* The different operations are +* - XISF_SPR_READ: Read Sector Protection Register +* - XISF_SPR_WRITE: Write Sector Protection Register +* - XISF_SPR_ERASE: Erase Sector Protection Register +* - XISF_SP_ENABLE: Enable Sector Protection +* - XISF_SP_DISABLE: Disable Sector Protection +* @param BufferPtr is a pointer to the memory where the SPR content is +* read to/written from. This argument can be NULL if the +* Operation is SprErase, SpEnable and SpDisable. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - The SPR content is stored at the fourth location pointed +* by the BufferPtr when performing XISF_SPR_READ operation. +* - For Intel, STM, Winbond and Spansion Serial Flash, the user +* application must call the XIsf_WriteEnable() API by passing +* XISF_WRITE_ENABLE as an argument, before calling the +* XIsf_SectorProtect() API, for Sector Protect Register Write +* (XISF_SPR_WRITE) operation. +* - Atmel Flash supports all these Sector Protect operations. +* - Intel, STM, Winbond and Spansion Flash support only Sector +* Protect Read and Sector Protect Write operations. +* +******************************************************************************/ +int XIsf_SectorProtect(XIsf *InstancePtr, XIsf_SpOperation Operation, + u8 *BufferPtr) +{ + int Status = (int)(XST_FAILURE); + u8 Mode; + + switch (Operation) { + case XISF_SPR_READ: + Status = SprRead(InstancePtr, BufferPtr); + break; + + case XISF_SPR_WRITE: + Status = SprProgram(InstancePtr, BufferPtr); + break; + + case XISF_SPR_ERASE: + Status = SprErase(InstancePtr); + break; + + case XISF_SP_ENABLE: + Status = SpEnable(InstancePtr); + break; + + case XISF_SP_DISABLE: + Status = SpDisable(InstancePtr); + break; + + default: + /* Added Comment for MISRA C */ + break; + } + + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function reads the content of the Sector Protection Register(SPR). +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param ReadPtr is a pointer to the memory where the SPR content is +* copied. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - This operation is supported for Atmel, Intel, STM, Winbond +* and Spansion Serial Flash. +* - The SPR content is stored at the fourth location pointed +* by the ReadPtr for Atmel Serial Flash and at second location +* for STM/Intel/Winbond/Spansion Serial Flash. +* +******************************************************************************/ +static int SprRead(XIsf *InstancePtr, u8 *ReadPtr) +{ + int Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + + + if (ReadPtr == NULL) { + return (int)(XST_FAILURE); + } + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + u32 Index; + + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_READ; + + for(Index = 1; Index < (InstancePtr->NumOfSectors + + XISF_CMD_SEND_EXTRA_BYTES); Index++) { + InstancePtr->WriteBufPtr[Index] = XISF_DUMMYBYTE; + } + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr, + InstancePtr->NumOfSectors + + XISF_CMD_SEND_EXTRA_BYTES); + +#else + + Status = XIsf_GetStatus(InstancePtr, ReadPtr); + +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + return (int)(XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function writes to the Sector Protection Register(SPR). +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferPtr is the pointer to the data to be written to SPR. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This operation is supported for Atmel, Intel, STM, Winbond and +* Spansion Serial Flash. +* +******************************************************************************/ +static int SprProgram(XIsf *InstancePtr, u8 *BufferPtr) +{ + int Status; + + Xil_AssertNonvoid(InstancePtr != NULL); + + if (BufferPtr == NULL) { + return (int)(XST_FAILURE); + } + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + u32 Index; + + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1; + InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2; + InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3; + InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_PROGRAM; + + for(Index = 4; Index < (InstancePtr->NumOfSectors + + XISF_CMD_SEND_EXTRA_BYTES); Index++) { + InstancePtr->WriteBufPtr[Index] = *BufferPtr++; + } + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + InstancePtr->NumOfSectors + + XISF_CMD_SEND_EXTRA_BYTES); +#else + + Status = XIsf_Write(InstancePtr, XISF_WRITE_STATUS_REG, + (void*) BufferPtr); + +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + return (int)(XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function erases the content of the Sector Protection Register(SPR). +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int SprErase(XIsf *InstancePtr) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1; + InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2; + InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3; + InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_ERASE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_CMD_SEND_EXTRA_BYTES); + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function enables Sector Protection. Sectors specified for protection in +* the Sector Protection Register are protected by using this operation. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int SpEnable(XIsf *InstancePtr) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1; + InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2; + InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3; + InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_ENABLE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_CMD_SEND_EXTRA_BYTES); + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function Disables Sector Protection. +* +* @param InstancePtr is a pointer to the XIsf instance. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int SpDisable(XIsf *InstancePtr) +{ + int Status = (int)(XST_FAILURE); + + Xil_AssertNonvoid(InstancePtr != NULL); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1; + InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2; + InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3; + InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_DISABLE; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_CMD_SEND_EXTRA_BYTES); + + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} diff --git a/lib/sw_services/xilisf/src/xilisf_write.c b/lib/sw_services/xilisf/src/xilisf_write.c new file mode 100644 index 00000000..74105155 --- /dev/null +++ b/lib/sw_services/xilisf/src/xilisf_write.c @@ -0,0 +1,975 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xilisf_write.c +* +* This file contains the library functions to write to the Serial Flash +* devices. Refer xilisf.h for detailed description. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who      Date     Changes
+* ----- -------  -------- -----------------------------------------------
+* 1.00a ksu/sdm  03/03/08 First release
+* 2.01a sdm      01/04/10 Added Support for Winbond W25QXX/W25XX devices
+* 2.04a sdm      08/17/10 Updated to support Numonyx (N25QXX) and Spansion
+*			  flash memories
+* 3.00a srt	 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
+*			  Added support to SST flash on SPI PS interface.
+* 5.0   sb	 08/05/14 Updated support for > 128 MB flash for PSQSPI
+*			  interface.
+*			  Changed API:
+*				WriteData()
+*				XIsf_Write()
+* 5.2  asa       05/12/15 Added support for Micron (N25Q256A) flash part
+* 						  which supports 4 byte addressing.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilisf.h" + +/************************** Constant Definitions *****************************/ +#define SIXTEENMB 0x1000000 /**< Sixteen MB */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr, + u32 ByteCount); +extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address); + +#ifdef XPAR_XISF_INTERFACE_PSQSPI +extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel); +#endif +static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, + const u8 *BufferPtr, u32 ByteCount); +static int AutoPageWrite(XIsf *InstancePtr, u32 Address); +static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr, + u32 ByteOffset, u32 NumBytes); +static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum, + u32 Address); +static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum, + u32 Address); +static int WriteSR(XIsf *InstancePtr, u8 SRData); +static int WriteSR2(XIsf *InstancePtr, u8 *SRData); +static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr); + +/************************** Variable Definitions *****************************/ +extern u32 XIsf_StatusEventInfo; +extern unsigned int XIsf_ByteCountInfo; +/************************** Function Definitions ******************************/ + + +/*****************************************************************************/ +/** +* +* This API writes the data to the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Operation is the type of write operation to be performed on the +* Serial Flash. +* The different operations are +* - XISF_WRITE: Normal Write +* - XISF_DUAL_IP_PAGE_WRITE: Dual Input Fast Program +* - XISF_DUAL_IP_EXT_PAGE_WRITE: Dual Input Extended Fast Program +* - XISF_QUAD_IP_PAGE_WRITE: Quad Input Fast Program +* - XISF_QUAD_IP_EXT_PAGE_WRITE: Quad Input Extended Fast Program +* - XISF_AUTO_PAGE_WRITE: Auto Page Write +* - XISF_BUFFER_WRITE: Buffer Write +* - XISF_BUF_TO_PAGE_WRITE_WITH_ERASE: Buffer to Page Transfer +* with Erase +* - XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE: Buffer to Page Transfer +* without Erase +* - XISF_WRITE_STATUS_REG: Status Register Write +* - XISF_WRITE_STATUS_REG2: 2 byte Status Register Write +* - XISF_OTP_WRITE: OTP Write. +* +* @param OpParamPtr is pointer to a structure variable which contains +* operational parameters of the specified operation. +* This parameter type is dependant on value of first argument +* (Operation). +* +* - Normal Write (XISF_WRITE), Dual Input Fast Program +* (XISF_DUAL_IP_PAGE_WRITE), Dual Input Extended Fast Program +* (XISF_DUAL_IP_EXT_PAGE_WRITE), Quad Input Fast Program +* (XISF_QUAD_IP_PAGE_WRITE), Quad Input Extended Fast Program +* (XISF_QUAD_IP_EXT_PAGE_WRITE): +* The OpParamPtr must be of type struct XIsf_WriteParam. +* OpParamPtr->Address is the start address in the Serial Flash. +* OpParamPtr->WritePtr is a pointer to the data to be written to +* the Serial Flash. +* OpParamPtr->NumBytes is the number of bytes to be written to +* Serial Flash. +* This operation is supported for Atmel, Intel, STM, Winbond and +* Spansion Serial Flash. +* +* - Auto Page Write (XISF_AUTO_PAGE_WRITE): +* The OpParamPtr must be of 32 bit unsigned integer variable. +* This is the address of page number in the Serial Flash which is +* to be refreshed. +* This operation is only supported for Atmel Serial Flash. +* +* - Buffer Write (XISF_BUFFER_WRITE): +* The OpParamPtr must be of type struct +* XIsf_BufferToFlashWriteParam. +* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the +* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or +* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of +* AT45DB011D Flash as it contains a single buffer. +* OpParamPtr->WritePtr is a pointer to the data to be written to +* the Serial Flash SRAM Buffer. +* OpParamPtr->ByteOffset is byte offset in the buffer from where +* the data is to be written. +* OpParamPtr->NumBytes is number of bytes to be written to the +* Buffer. +* This operation is supported only for Atmel Serial Flash. +* +* - Buffer To Memory Write With Erase +* (XISF_BUF_TO_PAGE_WRITE_WITH_ERASE)/ +* Buffer To Memory Write Without Erase +* (XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE): +* The OpParamPtr must be of type struct +* XIsf_BufferToFlashWriteParam. +* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the +* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or +* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of +* AT45DB011D Flash as it contains a single buffer. +* OpParamPtr->Address is starting address in the Serial Flash +* memory from where the data is to be written. +* These operations are only supported for Atmel Serial Flash. +* +* - Write Status Register (XISF_WRITE_STATUS_REG): +* The OpParamPtr must be of type of 8 bit unsigned integer +* variable. This is the value to be written to the Status +* Register. +* This operation is only supported for Intel, STM Winbond and +* Spansion Serial Flash. +* +* - Write Status Register2 (XISF_WRITE_STATUS_REG2): +* The OpParamPtr must be of type (u8 *) and should point to two +* 8 bit unsigned integer values. This is the value to be written +* to the 16 bit Status Register. +* This operation is only supported in Winbond (W25Q) Serial Flash. +* +* - One Time Programmable Area Write (XISF_OTP_WRITE): +* The OpParamPtr must be of type struct XIsf_WriteParam. +* OpParamPtr->Address is the address in the SRAM Buffer of the +* Serial Flash to which the data is to be written. +* OpParamPtr->WritePtr is a pointer to the data to be written to +* the Serial Flash. +* OpParamPtr->NumBytes should be set to 1 when performing +* OTPWrite operation. +* This operation is only supported for Intel Serial Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - Application must fill the structure elements of the third +* argument and pass its pointer by type casting it with void +* pointer. +* - For Intel, STM, Winbond and Spansion Serial Flash, the user +* application must call the XIsf_WriteEnable() API by passing +* XISF_WRITE_ENABLE as an argument, before calling the +* XIsf_Write() API. +* +******************************************************************************/ +int XIsf_Write(XIsf *InstancePtr, XIsf_WriteOperation Operation, + void *OpParamPtr) +{ + int Status = (int)XST_FAILURE; + u8 Mode; + XIsf_WriteParam *WriteParamPtr; + XIsf_BufferWriteParam *BufferWriteParamPtr; + XIsf_BufferToFlashWriteParam *BufferToFlashWriteParamPtr; + + if (InstancePtr == NULL) { + return (int)XST_FAILURE; + } + + if (InstancePtr->IsReady != TRUE) { + return (int)XST_FAILURE; + } + + if (NULL == OpParamPtr) { + return (int)XST_FAILURE; + } + + switch (Operation) { + case XISF_WRITE: + WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(WriteParamPtr != NULL); + Status = WriteData(InstancePtr, + XISF_CMD_PAGEPROG_WRITE, + WriteParamPtr->Address, + WriteParamPtr->WritePtr, + WriteParamPtr->NumBytes); + break; + + case XISF_AUTO_PAGE_WRITE: + Status = AutoPageWrite(InstancePtr, + *((u32*)(void *) OpParamPtr)); + break; + + case XISF_BUFFER_WRITE: + BufferWriteParamPtr = (XIsf_BufferWriteParam*) + (void *) OpParamPtr; + Xil_AssertNonvoid(BufferWriteParamPtr != NULL); + Status = BufferWrite(InstancePtr, + BufferWriteParamPtr->BufferNum, + BufferWriteParamPtr->WritePtr, + BufferWriteParamPtr->ByteOffset, + BufferWriteParamPtr->NumBytes); + break; + + case XISF_BUF_TO_PAGE_WRITE_WITH_ERASE: + BufferToFlashWriteParamPtr = + (XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL); + Status = BufferToFlashWriteWithErase(InstancePtr, + BufferToFlashWriteParamPtr->BufferNum, + BufferToFlashWriteParamPtr->Address); + break; + + case XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE: + BufferToFlashWriteParamPtr = + (XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL); + Status = BufferToFlashWriteWithoutErase(InstancePtr, + BufferToFlashWriteParamPtr->BufferNum, + BufferToFlashWriteParamPtr->Address); + break; + + case XISF_WRITE_STATUS_REG: + Status = WriteSR(InstancePtr, + *((u8*)(void *) OpParamPtr)); + break; + + case XISF_OTP_WRITE: + WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(WriteParamPtr != NULL); + if (1 == WriteParamPtr->NumBytes) { + Status = WriteOTPData(InstancePtr, + WriteParamPtr->Address, + WriteParamPtr->WritePtr); + } + break; + + case XISF_WRITE_STATUS_REG2: + Status = WriteSR2(InstancePtr, + (u8*)(void *) OpParamPtr); + break; + +#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \ + || (XPAR_XISF_FLASH_FAMILY == SPANSION)) + case XISF_QUAD_IP_PAGE_WRITE: + WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(WriteParamPtr != NULL); + Status = WriteData(InstancePtr, + XISF_CMD_QUAD_IP_PAGE_WRITE, + WriteParamPtr->Address, + WriteParamPtr->WritePtr, + WriteParamPtr->NumBytes); + break; + +#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) || + (XPAR_XISF_FLASH_FAMILY == STM) || + (XPAR_XISF_FLASH_FAMILY == SPANSION))*/ + +#if (XPAR_XISF_FLASH_FAMILY == STM) + case XISF_DUAL_IP_PAGE_WRITE: + WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(WriteParamPtr != NULL); + Status = WriteData(InstancePtr, + XISF_CMD_DUAL_IP_PAGE_WRITE, + WriteParamPtr->Address, + WriteParamPtr->WritePtr, + WriteParamPtr->NumBytes); + break; + + case XISF_DUAL_IP_EXT_PAGE_WRITE: + WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(WriteParamPtr != NULL); + Status = WriteData(InstancePtr, + XISF_CMD_DUAL_IP_EXT_PAGE_WRITE, + WriteParamPtr->Address, + WriteParamPtr->WritePtr, + WriteParamPtr->NumBytes); + break; + + case XISF_QUAD_IP_EXT_PAGE_WRITE: + WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr; + Xil_AssertNonvoid(WriteParamPtr != NULL); + Status = WriteData(InstancePtr, + XISF_CMD_QUAD_IP_EXT_PAGE_WRITE, + WriteParamPtr->Address, + WriteParamPtr->WritePtr, + WriteParamPtr->NumBytes); + break; +#endif /* (XPAR_XISF_FLASH_FAMILY == STM) */ + + default: + break; + } + + Mode = XIsf_GetTransferMode(InstancePtr); + + if(Mode == XISF_INTERRUPT_MODE){ + InstancePtr->StatusHandler(InstancePtr, + XIsf_StatusEventInfo, XIsf_ByteCountInfo); + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function writes the data to the specified address locations in Serial +* Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the address in the Serial Flash memory, where the +* data is to be written. +* @param BufferPtr is a pointer to the data to be written to Serial +* Flash. +* @param ByteCount is the number of bytes to be written. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - A minimum of one byte and a maximum of one Page can be +* written using this function. +* - This operation is supported for Atmel, Intel, STM, Winbond +* and Spansion Serial Flash. +* +******************************************************************************/ +static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, + const u8 *BufferPtr, u32 ByteCount) +{ + u8 Mode; + u32 Index; + u32 BankSel; + u32 RealAddr; + int Status; + u8 FlagStatus[2] = {0}; + u8 FlashStatus[2] = {0}; + u8 * NULLPtr = NULL; + const u8 * LocalBufPtr = BufferPtr; +#ifdef XPAR_XISF_INTERFACE_PSQSPI + u32 FlashMake = InstancePtr->ManufacturerID; +#endif + u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 }; + u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0}; + + if ((ByteCount <= 0) || (ByteCount > InstancePtr->BytesPerPage)) { + return (int)XST_FAILURE; + } + + if (LocalBufPtr == NULL) { + return (int)XST_FAILURE; + } + + /* + * Translate address based on type of connection + * If stacked assert the slave select based on address + */ + RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address); + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + /* + * 0x18 is the DeviceIDMemSize for different make of + * flashes of size 16MB + */ + if(InstancePtr->DeviceIDMemSize > 0x18) { + + /* + * Get the Transfer Mode + */ + Mode = XIsf_GetTransferMode(InstancePtr); + + /* + * Seting the transfer mode to Polled Mode before + * performing the Bank Select operation. + */ + XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE); + + /* + * Calculate bank + */ + BankSel = RealAddr/SIXTEENMB; + /* + * Select bank + */ + (void)SendBankSelect(InstancePtr, BankSel); + + /* + * Restoring the transfer mode back + */ + XIsf_SetTransferMode(InstancePtr, Mode); + } +#endif +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + if (InstancePtr->FourByteAddrMode == TRUE) { + InstancePtr->WriteBufPtr[BYTE1] = Command; + InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr); + for(Index = 5U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE); + Index++) { + InstancePtr->WriteBufPtr[Index] = *LocalBufPtr; + LocalBufPtr += 1; + } + } else { +#endif + InstancePtr->WriteBufPtr[BYTE1] = Command; + InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr); + for(Index = 4U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES); + Index++) { + InstancePtr->WriteBufPtr[Index] = *LocalBufPtr; + LocalBufPtr += 1; + } +#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + } +#endif + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + /* + * Enable write before transfer + */ + Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE); +#endif + if (InstancePtr->FourByteAddrMode == TRUE) { + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, + (ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE)); + } else { + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, + (ByteCount + XISF_CMD_SEND_EXTRA_BYTES)); + } + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } + +#ifdef XPAR_XISF_INTERFACE_PSQSPI + if((InstancePtr->NumDie > 1) && + (FlashMake == XISF_MANUFACTURER_ID_MICRON)) { + Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, + (u32)sizeof(ReadFlagSRCmd)); + if(Status != (int)XST_SUCCESS){ + return (int)XST_FAILURE; + } + } + + /* + * Wait for the write command to the Flash to be completed, it takes + * some time for the data to be written + */ + while (1) { + /* + * Poll the status register of the Flash to determine when it + * completes, by sending a read status command and receiving + * status byte + */ + Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf, + FlashStatus, (u32)sizeof(ReadStatusCmdBuf)); + if(Status != (int)XST_SUCCESS){ + return (int)XST_FAILURE; + } + + /* + * If status indicates the write is done, then stop waiting, + * if a value of 0xFF in the status byte is read from the + * device and this loop never exits, the device slave select is + * possibly incorrect such that the device status is not being + * read + */ + if ((FlashStatus[1] & 0x01) == 0) { + break; + } + } + + if((InstancePtr->NumDie > 1) && + (FlashMake == XISF_MANUFACTURER_ID_MICRON)) { + Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, + (u32)sizeof(ReadFlagSRCmd)); + if(Status != (int)XST_SUCCESS){ + return (int)XST_FAILURE; + } + } +#endif + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function Auto rewrites the contents of a Page in the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the address of the page to be refreshed. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int AutoPageWrite(XIsf *InstancePtr, u32 Address) +{ + int Status = (int)XST_FAILURE; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Address != 0); + + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_AUTOPAGE_WRITE; + InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (XISF_DUMMYBYTE); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_CMD_SEND_EXTRA_BYTES); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function writes data to the specified SRAM buffer of the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferNum specifies the internal SRAM Buffer of the Serial +* Flash. The valid values are XISF_PAGE_BUFFER1 or +* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of +* Atmel AT45DB011D Serial Flash as it contains a single buffer. +* @param WritePtr is the pointer to the data to be written to the +* Serial Flash SRAM Buffer. +* @param ByteOffset is the byte offset in the buffer from where the +* data is to be written. +* @param NumBytes is the number of bytes to be written to the Buffer. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - A minimum of one byte and a maximum of one SRAM buffer can be +* written using this function. +* - This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr, + u32 ByteOffset, u32 NumBytes) +{ + int Status = (int)XST_FAILURE; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferNum != 0); + Xil_AssertNonvoid(WritePtr != NULL); + Xil_AssertNonvoid(ByteOffset != 0); + Xil_AssertNonvoid(NumBytes != 0); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + u16 Index; + + /* + * Check buffer number is valid or not. + */ + if ((BufferNum == XISF_PAGE_BUFFER1) || + (BufferNum == XISF_PAGE_BUFFER2)) { + if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) && + (BufferNum != XISF_PAGE_BUFFER1)) { + return (int)XST_FAILURE; + } + } + else{ + return (int)XST_FAILURE; + } + + if (WritePtr == NULL) { + return (int)XST_FAILURE; + } + + if (ByteOffset > InstancePtr->BytesPerPage) { + return (int)XST_FAILURE; + } + + if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) { + return (int)XST_FAILURE; + } + + + if (BufferNum == XISF_PAGE_BUFFER1) { + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER1_WRITE; + } + else{ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER2_WRITE; + } + InstancePtr->WriteBufPtr[BYTE2] = (u8) (0x00); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) ByteOffset; + + + for(Index = 4; Index < NumBytes + XISF_CMD_SEND_EXTRA_BYTES; Index++) { + InstancePtr->WriteBufPtr[Index] = *WritePtr++; + } + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + (NumBytes + XISF_CMD_SEND_EXTRA_BYTES)); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function first erases a page and then writes data from the specified +* internal SRAM buffer to the specified locations in the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferNum specifies the internal SRAM Buffer, from which the +* data needs to be written to the Serial Flash. The valid values +* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 +* is not valid in the case of Atmel AT45DB011D Serial Flash as it +* contains a single buffer. +* @param Address is the starting address in the Serial Flash where +* the data has to be written. Byte address in this address is +* ignored as an entire Page is transferred using this API. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - A minimum of one Page and a maximum of one Page can be +* written using this function. +* - This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum, + u32 Address) +{ + int Status = (int)XST_FAILURE; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferNum != 0); + Xil_AssertNonvoid(Address != 0); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Check whether the buffer number is valid or not. + */ + if ((BufferNum == XISF_PAGE_BUFFER1) || + (BufferNum == XISF_PAGE_BUFFER2)) { + if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) && + (BufferNum != XISF_PAGE_BUFFER1)) { + return (int)XST_FAILURE; + } + } + else { + return (int)XST_FAILURE; + } + + if (BufferNum == XISF_PAGE_BUFFER1) { + /* + * Buffer 1 to Page Program With Erase. + */ + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_ERASE_BUF1TOPAGE_WRITE; + } else { + /* + * Buffer 2 to Page Program With Erase. + */ + InstancePtr->WriteBufPtr[BYTE1] = + XISF_CMD_ERASE_BUF2TOPAGE_WRITE; + } + InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_CMD_SEND_EXTRA_BYTES); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function writes data from the specified internal SRAM buffer to the +* specified locations in the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param BufferNum specifies the internal SRAM Buffer, from which the +* data needs to be written to the Serial Flash. The valid values +* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 +* is not valid in the case of Atmel AT45DB011D Serial Flash as it +* contains a single buffer. +* @param Address is the starting address in the Serial Flash where +* data has to be written. Byte address in this address will be +* ignored as an entire page of data is transferred using this +* operation. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* - A minimum of one Page and a maximum of one Page can be +* written using this function. +* - This operation is only supported for Atmel Serial Flash. +* +******************************************************************************/ +static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum, + u32 Address) +{ + int Status = (int)XST_FAILURE; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferNum != 0); + Xil_AssertNonvoid(Address != 0); + +#if (XPAR_XISF_FLASH_FAMILY == ATMEL) + /* + * Check whether the buffer number is valid or not. + */ + if ((BufferNum == XISF_PAGE_BUFFER1) || + (BufferNum == XISF_PAGE_BUFFER2)) { + if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) && + (XISF_PAGE_BUFFER1 != 1)) { + return (int)XST_FAILURE; + } + } + else { + return (int)XST_FAILURE; + } + + if (BufferNum == XISF_PAGE_BUFFER1) { + /* + * Buffer 1 to Page Program Without Erase. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF1TOPAGE_WRITE; + } + else { + /* + * Buffer 2 to Page Program Without Erase. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF2TOPAGE_WRITE; + } + + InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE); + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_CMD_SEND_EXTRA_BYTES); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function writes data to the Status Register of the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param SRData is the value to be written to the Status Register +* of the Serial Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This operation is only supported in Intel, STM, Winbond and +* Spansion Serial Flash. This is the write of Status Register 1 +* for Winbond devices, write of Status Register 2 is handled by +* WriteSR2. +* +******************************************************************************/ +static int WriteSR(XIsf *InstancePtr, u8 SRData) +{ + int Status = XST_FAILURE; + +#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ + (XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST)) + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE; + InstancePtr->WriteBufPtr[BYTE2] = SRData; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_STATUS_RDWR_BYTES); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \\ + (XPAR_XISF_FLASH_FAMILY == WINBOND) || + (XPAR_XISF_FLASH_FAMILY == SPANSION)) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function writes data to Status Register of the Serial Flash. This API +* should be used to write to the 16 bit status register in Winbond Quad Flash +* (W25QXX). +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param SRData is of type (u8*) and points to the 16 bit value to be +* written to the Status Register of the Serial Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note This operation is only supported in Winbond (W25QXX) Serial +* Flash. +* +******************************************************************************/ +static int WriteSR2(XIsf *InstancePtr, u8 *SRData) +{ + int Status = (int)XST_FAILURE; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SRData != NULL); + +#if (XPAR_XISF_FLASH_FAMILY == WINBOND) + /* + * Prepare the Write Buffer. + */ + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE; + InstancePtr->WriteBufPtr[BYTE2] = *SRData++; + InstancePtr->WriteBufPtr[BYTE3] = *SRData; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_STATUS_RDWR_BYTES + 1); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */ + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function writes one byte of data to the OTP area in the Serial Flash. +* +* @param InstancePtr is a pointer to the XIsf instance. +* @param Address is the address in the OTP area, where to write data. +* @param BufferPtr is the pointer to the data to be written into OTP +* region of Serial Flash. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note +* - A minimum of one byte and a maximum of one byte can be +* written using this function. +* - This operation is supported only for Intel Serial Flash. +* +******************************************************************************/ +static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr) +{ + int Status = (int)XST_FAILURE; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Address != 0); + Xil_AssertNonvoid(BufferPtr != NULL); + + +#if (XPAR_XISF_FLASH_FAMILY == INTEL) + if (BufferPtr == NULL) { + return (int)XST_FAILURE; + } + + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_OTP_WRITE; + InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16); + InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8); + InstancePtr->WriteBufPtr[BYTE4] = (u8) Address; + InstancePtr->WriteBufPtr[BYTE5] = *BufferPtr; + + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL, + XISF_OTP_RDWR_EXTRA_BYTES); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } +#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */ + + return Status; +}