From 6c219982704c34b591df464f497e6814de5bec20 Mon Sep 17 00:00:00 2001 From: naga sureshkumar relli Date: Tue, 9 Jun 2015 11:24:03 +0530 Subject: [PATCH] xilflash_v4_0: deprecated version 4.0 and created new version 4.1 This patch deprecates the xilflash_v4_0 and creates new version xilflash_v4_1. Signed-off-by: naga sureshkumar relli --- lib/sw_services/xilflash/data/xilflash.mld | 70 + lib/sw_services/xilflash/data/xilflash.tcl | 117 + .../examples/xilflash_devicecontrol_example.c | 279 ++ .../xilflash_platform_flash_example.c | 266 ++ .../examples/xilflash_protection_example.c | 251 ++ .../examples/xilflash_readwrite_example.c | 240 ++ lib/sw_services/xilflash/src/Makefile | 88 + .../xilflash/src/include/xilflash.h | 634 ++++ .../xilflash/src/include/xilflash_amd.h | 157 + .../xilflash/src/include/xilflash_cfi.h | 156 + .../xilflash/src/include/xilflash_intel.h | 280 ++ .../src/include/xilflash_properties.h | 142 + lib/sw_services/xilflash/src/xilflash.c | 682 ++++ lib/sw_services/xilflash/src/xilflash_amd.c | 2441 ++++++++++++++ lib/sw_services/xilflash/src/xilflash_cfi.c | 870 +++++ lib/sw_services/xilflash/src/xilflash_intel.c | 2973 +++++++++++++++++ 16 files changed, 9646 insertions(+) create mode 100755 lib/sw_services/xilflash/data/xilflash.mld create mode 100755 lib/sw_services/xilflash/data/xilflash.tcl create mode 100644 lib/sw_services/xilflash/examples/xilflash_devicecontrol_example.c create mode 100644 lib/sw_services/xilflash/examples/xilflash_platform_flash_example.c create mode 100644 lib/sw_services/xilflash/examples/xilflash_protection_example.c create mode 100644 lib/sw_services/xilflash/examples/xilflash_readwrite_example.c create mode 100644 lib/sw_services/xilflash/src/Makefile create mode 100644 lib/sw_services/xilflash/src/include/xilflash.h create mode 100644 lib/sw_services/xilflash/src/include/xilflash_amd.h create mode 100644 lib/sw_services/xilflash/src/include/xilflash_cfi.h create mode 100644 lib/sw_services/xilflash/src/include/xilflash_intel.h create mode 100644 lib/sw_services/xilflash/src/include/xilflash_properties.h create mode 100644 lib/sw_services/xilflash/src/xilflash.c create mode 100644 lib/sw_services/xilflash/src/xilflash_amd.c create mode 100644 lib/sw_services/xilflash/src/xilflash_cfi.c create mode 100644 lib/sw_services/xilflash/src/xilflash_intel.c diff --git a/lib/sw_services/xilflash/data/xilflash.mld b/lib/sw_services/xilflash/data/xilflash.mld new file mode 100755 index 00000000..df148f2c --- /dev/null +++ b/lib/sw_services/xilflash/data/xilflash.mld @@ -0,0 +1,70 @@ +############################################################################### +# +# Copyright (C) 2007 - 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. +# +############################################################################### +## @BEGIN_CHANGELOG EDK_LS3 +## Added platfrom_flash paramter to select whether a Xilinx Platform Flash XL +## device is present in the system and is to be used. +## +## @END_CHANGELOG +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 3.00a sdm 03/03/11 Removed static flash parameters in the library +# 3.00a sdm 03/23/11 Added new parameters to enable support for flash families +# +############################################################################## + +OPTION psf_version = 2.1; + +BEGIN LIBRARY xilflash + OPTION drc = flash_drc; + OPTION copyfiles = all; + OPTION REQUIRES_OS = (standalone xilkernel); + OPTION REQUIRES_INTERFACE = (xilflash); + OPTION supported_peripherals = (opb_emc_v2_00_a plb_emc mch_opb_emc xps_mch_emc axi_emc); + OPTION APP_LINKER_FLAGS = "-lxilflash"; + OPTION desc = "Xilinx Flash library for Intel/AMD CFI compliant parallel flash"; + OPTION VERSION = 4.1; + OPTION NAME = xilflash; + PARAM name = enable_intel, desc = "Enables support for Intel family devices", type = bool, default = true; + PARAM name = enable_amd, desc = "Enables support for AMD family devices", type = bool, default = false; + + #deprecated parameters + PARAM name = part_mode, state = DEPRECATED, desc = "Operational mode of each part in bytes. Indicates the data bus width of the Flash part actually used.", type = int, default = 2; + PARAM name = num_parts, state = DEPRECATED, desc = "Number of flash device parts in the array that forms the Flash Memory", type = int, default = 2; + PARAM name = part_width, state = DEPRECATED, desc = "Width of each part in bytes. Indicates the data bus width supported by the Flash part", type = int, default = 2; + PARAM name = base_address, state = DEPRECATED, desc = "Flash Base Address in Hex", type = int, default = 0x0; + PARAM name = flash_family, state = DEPRECATED, desc = "Indicates the flash family type. Enter 1 for INTEL and 2 for AMD.", type = int, default = 1; + PARAM name = platform_flash, state = DEPRECATED, desc = "Indicates the flash device type. Enter 1 for Platfrom flash and 0 for others.", type = int, default = 0; + +END LIBRARY diff --git a/lib/sw_services/xilflash/data/xilflash.tcl b/lib/sw_services/xilflash/data/xilflash.tcl new file mode 100755 index 00000000..dbfaf12e --- /dev/null +++ b/lib/sw_services/xilflash/data/xilflash.tcl @@ -0,0 +1,117 @@ +############################################################################### +# +# Copyright (C) 2007 - 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. +# +############################################################################### + +## @BEGIN_CHANGELOG EDK_LS3 +## Added XPAR_XFL_PLATFORM_FLASH to be generated in the xparameters.h. +## If the user selects Platform Flash XL device to be used then +## parameter will be set to 1. +## +## @END_CHANGELOG +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 2.03a sdm 09/24/10 updated to use Tcl commands instead of unix commands +# 3.00a sdm 03/03/11 Removed static flash parameters in the library +# 3.00a sdm 03/23/11 Added new parameters to enable support for flash families +# +############################################################################## + +#--------------------------------------------- +# Flash_drc +#--------------------------------------------- +proc flash_drc {libhandle} { + +} + +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 libxilflash.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 parameters for Flash family support + puts $file_handle "/* Xilinx EDK Parallel Flash Library (XilFlash) User Settings */" + set enable_intel [common::get_property CONFIG.enable_intel $libhandle] + set enable_amd [common::get_property CONFIG.enable_amd $libhandle] + + if {$enable_intel == false && $enable_amd == false} { + error "ERROR: no flash family enabled. enable atleast one flash family in the bsp settings and rebuild the libraries" + } + + if {$enable_intel == true} { + puts $file_handle "\#define XPAR_XFL_DEVICE_FAMILY_INTEL" + } + + if {$enable_amd == true} { + puts $file_handle "\#define XPAR_XFL_DEVICE_FAMILY_AMD" + } + + 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/xilflash/examples/xilflash_devicecontrol_example.c b/lib/sw_services/xilflash/examples/xilflash_devicecontrol_example.c new file mode 100644 index 00000000..b5970e37 --- /dev/null +++ b/lib/sw_services/xilflash/examples/xilflash_devicecontrol_example.c @@ -0,0 +1,279 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_devicecontrol_example.c +* +* This file contains a design example using the Generic Flash Library. +* This example displays the Flash device geometry and properties. The geometry +* and properties are fetched using Device Control API. +* +* +* @note None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.01a mta  10/09/07 First release
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 3.00a sdm  03/03/11 Updated to pass BaseAddress and Flash Width to _Initialize
+*		      API, as required by the new version of the library
+*
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include +#include +#include + +/************************** Constant Definitions *****************************/ + +/* + * The following constants define the baseaddress and width the flash memory. + * These 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 FLASH_BASE_ADDRESS XPAR_EMC_0_MEM0_BASEADDR + +/* + * The following constant defines the total byte width of the flash memory. The + * user needs to update this width based on the flash width in the design/board. + * The total flash width on some of the Xilinx boards is listed below. + * ------------------------------- + * Board Width + * ------------------------------- + * ML403 4 (32 bit) + * ML5xx 2 (16 bit) + * Spartan3S 1600E 2 (16 bit) + * Spartan-3A DSP 2 (16 bit) + * Spartan-3A 2 (16 bit) + * Spartan-3AN 2 (16 bit) + * ML605 2 (16 bit) + * SP605 2 (16 bit) + * SP601 1 (8 bit) + */ +#define FLASH_MEM_WIDTH 2 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +int FlashDeviceControlExample(void); + +/************************** Variable Definitions *****************************/ + +XFlash FlashInstance; /* XFlash Instance. */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Flash device control example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + Status = FlashDeviceControlExample(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function fetches and displays the geometry and properties of the Flash * +* device. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int FlashDeviceControlExample(void) +{ + int Status; + u32 Index; + DeviceCtrlParam IoctlParams; + + /* + * Initialize the Flash Library. + */ + Status = XFlash_Initialize(&FlashInstance, FLASH_BASE_ADDRESS, + FLASH_MEM_WIDTH, 0); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Reset the Flash Device. This clears the Status registers and puts + * the device in Read mode. + */ + Status = XFlash_Reset(&FlashInstance); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Fetch the flash device properties and display. + */ + Status = XFlash_DeviceControl(&FlashInstance, + XFL_DEVCTL_GET_PROPERTIES, &IoctlParams); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + xil_printf("\n\r\t\tFlash Properties\n\r"); + xil_printf("FlashProperties->PartID.ManufacturerID = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + PartID.ManufacturerID); + + xil_printf("FlashProperties->PartID.DeviceID = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + PartID.DeviceID); + + xil_printf("FlashProperties->PartID.DeviceID = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + PartID.CommandSet); + + xil_printf("FlashProperties->TimeTypical.WriteSingle_Us = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeTypical.WriteSingle_Us); + + xil_printf("FlashProperties->TimeTypical.WriteBuffer_Us = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeTypical.WriteBuffer_Us); + + xil_printf("FlashProperties->TimeTypical.EraseBlock_Ms = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeTypical.EraseBlock_Ms); + + xil_printf("FlashProperties->TimeTypical.EraseChip_Ms = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeTypical.EraseChip_Ms); + + xil_printf("FlashProperties->TimeMax.WriteSingle_Us = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeMax.WriteSingle_Us); + + xil_printf("FlashProperties->TimeMax.WriteBuffer_Us = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeMax.WriteBuffer_Us); + + xil_printf("FlashProperties->TimeMax.EraseBlock_Ms = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeMax.EraseBlock_Ms); + + xil_printf("FlashProperties->TimeMax.EraseChip_Ms = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + TimeMax.EraseChip_Ms); + + xil_printf("FlashProperties->ProgCap.WriteBufferSize = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + ProgCap.WriteBufferSize); + + xil_printf("FlashProperties->ProgCap.WriteBufferAlignMask = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr->ProgCap. + WriteBufferAlignmentMask); + + xil_printf("FlashProperties->ProgCap.EraseQueueSize = 0x%x\n\r", + IoctlParams.PropertiesParam.PropertiesPtr-> + ProgCap.EraseQueueSize); + + /* + * Fetch the flash device geometry and display. + */ + Status = XFlash_DeviceControl(&FlashInstance, + XFL_DEVCTL_GET_GEOMETRY, &IoctlParams); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + xil_printf("\n\r\n\r\t\tFlash Geometry\n\r"); + + xil_printf("FlashGeometry->BaseAddress = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr->BaseAddress); + + xil_printf("FlashGeometry->MemoryLayout = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr->MemoryLayout); + + xil_printf("FlashGeometry->DeviceSize = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr->DeviceSize); + + xil_printf("FlashGeometry->NumEraseRegions = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr->NumEraseRegions); + + xil_printf("FlashGeometry->NumBlocks = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr->NumBlocks); + + for(Index = 0; Index < IoctlParams.GeometryParam.GeometryPtr-> + NumEraseRegions; Index++) { + xil_printf("\tErase region %d\n\r", Index); + + xil_printf("Absolute Offset = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr-> + EraseRegion[Index].AbsoluteOffset); + + xil_printf("Absolute Block = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr-> + EraseRegion[Index].AbsoluteBlock); + + xil_printf("Num Of Block = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr-> + EraseRegion[Index].Number); + + xil_printf("Size Of Block = 0x%x\n\r", + IoctlParams.GeometryParam.GeometryPtr-> + EraseRegion[Index].Size); + } + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilflash/examples/xilflash_platform_flash_example.c b/lib/sw_services/xilflash/examples/xilflash_platform_flash_example.c new file mode 100644 index 00000000..184eef79 --- /dev/null +++ b/lib/sw_services/xilflash/examples/xilflash_platform_flash_example.c @@ -0,0 +1,266 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_platform_flash_example.c +* +* +* This file contains a design example using the Flash Library with the Xilinx +* Platform Flash XL device. This example tests Unlock, Erase, Read and Write +* features. The Page is unlocked, erased and data is written to the page. The +* data is read back and compared with the data written for correctness. +* This example also shows usage of XFlash_DeviceControl to set the Platform +* Flash XL device in the Async/Sync Mode. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a ksu  06/16/09 First release
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 3.00a sdm  03/03/11 Updated to pass BaseAddress and Flash Width to _Initialize
+*		      API, as required by the new version of the library
+*
+******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include + +/************************** Constant Definitions *****************************/ + +/* + * The following constants define the baseaddress and width the flash memory. + * These 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 FLASH_BASE_ADDRESS XPAR_EMC_0_MEM0_BASEADDR + +/* + * The following constant defines the total byte width of the flash memory. The + * user needs to update this width based on the flash width in the design/board. + * The total flash width on some of the Xilinx boards is listed below. + * ------------------------------- + * Board Width + * ------------------------------- + * ML403 4 (32 bit) + * ML5xx 2 (16 bit) + * Spartan3S 1600E 2 (16 bit) + * Spartan-3A DSP 2 (16 bit) + * Spartan-3A 2 (16 bit) + * Spartan-3AN 2 (16 bit) + * ML605 2 (16 bit) + * SP605 2 (16 bit) + * SP601 1 (8 bit) + */ +#define FLASH_MEM_WIDTH 2 + +#define FLASH_TEST_SIZE 4048 +#define START_ADDRESS 0x100000 + +/* + * The Sync and Async mode address + */ +#define ASYNC_ADDR 0x17BBE /* Config Register value for setting Async mode */ +#define SYNC_ADDR 0x07BBE /* Config Register value for setting Sync mode */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +int PlatformFlashReadWriteExample(void); + +/************************** Variable Definitions *****************************/ +XFlash FlashInstance; /* XFlash Instance. */ + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[FLASH_TEST_SIZE]; /* Buffer used to store the data read. */ +u8 WriteBuffer[FLASH_TEST_SIZE]; /* Write buffer. */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Platform Flash Read/Write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + Status = PlatformFlashReadWriteExample(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function writes, reads, and verifies the data to the Flash device. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int PlatformFlashReadWriteExample(void) +{ + int Status; + u32 Index; + DeviceCtrlParam IoctlParams; + + /* + * Initialize the Flash Library. The Platform Flash XL device is + * set into Async Mode during the initialization. + */ + Status = XFlash_Initialize(&FlashInstance, FLASH_BASE_ADDRESS, + FLASH_MEM_WIDTH, 1); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Reset the Flash Device. This clears the Status registers and puts + * the device in Read mode. + */ + Status = XFlash_Reset(&FlashInstance); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set ASYNC flash read mode. This call is for showing the + * usage of the XFlash_DeviceControl to set the Platform Flash XL + * device in Async Mode. + */ + IoctlParams.ConfigRegParam.Value = ASYNC_ADDR; + Status = XFlash_DeviceControl(&FlashInstance, + XFL_DEVCTL_SET_CONFIG_REG, &IoctlParams); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Reset the Flash Device. This clears the Status registers and puts + * the device in Read mode. + */ + Status = XFlash_Reset(&FlashInstance); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform an unlock operation before the erase operation for the Intel + * Flash. The erase operation will result in an error if the block is + * locked. + */ + Status = XFlash_Unlock(&FlashInstance, START_ADDRESS, 0); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + + /* + * Perform the Erase operation. + */ + Status = XFlash_Erase(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Flash Device. + */ + for(Index = 0; Index < FLASH_TEST_SIZE; Index++) { + WriteBuffer[Index] = Index + 0x5; + } + + /* + * Perform the Write operation. + */ + Status = XFlash_Write(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE, + WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the read operation. + */ + Status = XFlash_Read(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE, + ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < FLASH_TEST_SIZE; Index++) { + if(ReadBuffer[Index] != WriteBuffer[Index]) { + return XST_FAILURE; + } + } + + /* + * Set the Platform Flash XL device to Sync mode. This call is + * for showing the usage of the XFlash_DeviceControl to set the + * Platform Flash XL device in Sync Mode. + */ + IoctlParams.ConfigRegParam.Value = SYNC_ADDR; + Status = XFlash_DeviceControl(&FlashInstance, + XFL_DEVCTL_SET_CONFIG_REG, &IoctlParams); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilflash/examples/xilflash_protection_example.c b/lib/sw_services/xilflash/examples/xilflash_protection_example.c new file mode 100644 index 00000000..22a64f09 --- /dev/null +++ b/lib/sw_services/xilflash/examples/xilflash_protection_example.c @@ -0,0 +1,251 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_protection_example.c +* +* +* This file contains a design example using the Generic Flash Library. +* This example tests the Lock and UnLock features of the Flash Device. +* +* A block is Locked and an attempt is made to erase a Page in that block. This +* should return an error. The block is then unlocked and an attempt is made to +* erase a page in that block which should succeed. A page of data is written, +* read back and compared with the data written for correctness. +* +* @note This example has been tested with an Intel CFI compliant +* Flash device. +* This example has not been tested with an AMD CFI compliant Flash +* device. The AMD CFI compliant Flash devices require the user to +* apply a 12V DC voltage on the RP pin while performing the Lock +* and Unlock operations. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.01a mta  10/09/07 First release
+* 1.01a sdm  02/24/09 Updated the notes with information about using the example
+*		      with AMD CFI compliant Flash devices
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 3.00a sdm  03/03/11 Updated to pass BaseAddress and Flash Width to _Initialize
+*		      API, as required by the new version of the library
+*
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include +#include + +/************************** Constant Definitions *****************************/ + +/* + * The following constants define the baseaddress and width the flash memory. + * These 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 FLASH_BASE_ADDRESS XPAR_EMC_0_MEM0_BASEADDR + +/* + * The following constant defines the total byte width of the flash memory. The + * user needs to update this width based on the flash width in the design/board. + * The total flash width on some of the Xilinx boards is listed below. + * ------------------------------- + * Board Width + * ------------------------------- + * ML403 4 (32 bit) + * ML5xx 2 (16 bit) + * Spartan3S 1600E 2 (16 bit) + * Spartan-3A DSP 2 (16 bit) + * Spartan-3A 2 (16 bit) + * Spartan-3AN 2 (16 bit) + * ML605 2 (16 bit) + * SP605 2 (16 bit) + * SP601 1 (8 bit) + */ +#define FLASH_MEM_WIDTH 2 + +#define FLASH_TEST_SIZE 256 +#define START_ADDRESS 0x060000 +#define BLOCK_OFFSET_ADDR 0x068000 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +int FlashProtectionExample(void); + +/************************** Variable Definitions *****************************/ + +XFlash FlashInstance; /* XFlash Instance. */ + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[FLASH_TEST_SIZE]; /* Buffer used to store the data read. */ +u8 WriteBuffer[FLASH_TEST_SIZE]; /* Write buffer. */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Flash protection example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + Status = FlashProtectionExample(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function verifies the locking and unlocking features of the Flash device. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int FlashProtectionExample(void) +{ + int Status; + u32 Index; + + /* + * Initialize the Flash Library. + */ + Status = XFlash_Initialize(&FlashInstance, FLASH_BASE_ADDRESS, + FLASH_MEM_WIDTH, 0); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Reset the Flash Device. This clears the Status registers and puts + * the device in Read mode. + */ + Status = XFlash_Reset(&FlashInstance); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Lock the Block. + */ + Status = XFlash_Lock(&FlashInstance, BLOCK_OFFSET_ADDR, 0); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Erase operation. This should fail as the block is locked. + */ + Status = XFlash_Erase(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE); + if(Status == XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Unlock the Block. + */ + Status = XFlash_Unlock(&FlashInstance, BLOCK_OFFSET_ADDR, 0); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the Erase operation. This should succeed as the block is + * unlocked. + */ + Status = XFlash_Erase(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Flash Device. + */ + for(Index = 0; Index < FLASH_TEST_SIZE; Index++) { + WriteBuffer[Index] = (u8)Index; + } + + /* + * Perform the Write operation. + */ + Status = XFlash_Write(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE, + WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the read operation. + */ + Status = XFlash_Read(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE, + ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < FLASH_TEST_SIZE; Index++) { + if(ReadBuffer[Index] != (u8)Index) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilflash/examples/xilflash_readwrite_example.c b/lib/sw_services/xilflash/examples/xilflash_readwrite_example.c new file mode 100644 index 00000000..2422f2c1 --- /dev/null +++ b/lib/sw_services/xilflash/examples/xilflash_readwrite_example.c @@ -0,0 +1,240 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_readwrite_example.c +* +* +* This file contains a design example using the Flash Library. +* This example tests the Erase, Read and Write features. The Page is erased +* and data is written to the page. The data is read back and compared with +* the data written for correctness. +* +* @note The Erase operation on a CFI compliant Flash device will result +* in an error if the block is locked. +* This example performs an Unlock operation before Erase operation +* only on the Intel CFI compliant Flash device. The AMD CFI +* compliant Flash devices require the user to apply a 12V DC +* voltage on the RP pin while performing the Lock and Unlock +* operations. This example will not work with the AMD compliant +* Flash devices if the block is locked and the user doesn't +* perform an Unlock operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a mta  10/09/07 First release
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 1.01a sdm  02/24/09 a) Added code to perform an Unlock operation before the
+*                        Erase operation for Intel CFI compliant Flash devices
+*                     b) Updated the notes with information about using the
+*                        example with AMD CFI compliant Flash devices
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 3.00a sdm  03/03/11 Updated to pass BaseAddress and Flash Width to _Initialize
+*		      API, as required by the new version of the library
+*
+*
+******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include +/************************** Constant Definitions *****************************/ + +/* + * The following constants define the baseaddress and width the flash memory. + * These 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 FLASH_BASE_ADDRESS XPAR_EMC_0_MEM0_BASEADDR + +/* + * The following constant defines the total byte width of the flash memory. The + * user needs to update this width based on the flash width in the design/board. + * The total flash width on some of the Xilinx boards is listed below. + * ------------------------------- + * Board Width + * ------------------------------- + * ML403 4 (32 bit) + * ML5xx 2 (16 bit) + * Spartan3S 1600E 2 (16 bit) + * Spartan-3A DSP 2 (16 bit) + * Spartan-3A 2 (16 bit) + * Spartan-3AN 2 (16 bit) + * ML605 2 (16 bit) + * SP605 2 (16 bit) + * SP601 1 (8 bit) + */ +#define FLASH_MEM_WIDTH 2 + +#define FLASH_TEST_SIZE 4048 +#define START_ADDRESS 0x060000 +#define BLOCK_OFFSET_ADDR 0x068000 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +int FlashReadWriteExample(void); +/************************** Variable Definitions *****************************/ +XFlash FlashInstance; /* XFlash Instance. */ + +/* + * Buffers used during read and write transactions. + */ +u8 ReadBuffer[FLASH_TEST_SIZE]; /* Buffer used to store the data read. */ +u8 WriteBuffer[FLASH_TEST_SIZE]; /* Write buffer. */ + +/************************** Function Definitions ******************************/ + +/*****************************************************************************/ +/** +* +* Main function to execute the Flash read write example. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + Status = FlashReadWriteExample(); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function writes, reads, and verifies the data to the Flash device. +* +* @param None +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int FlashReadWriteExample(void) +{ + int Status; + u32 Index; + + /* + * Initialize the Flash Library. + */ + Status = XFlash_Initialize(&FlashInstance, FLASH_BASE_ADDRESS, + FLASH_MEM_WIDTH, 0); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Reset the Flash Device. This clears the Status registers and puts + * the device in Read mode. + */ + Status = XFlash_Reset(&FlashInstance); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform an unlock operation before the erase operation for the Intel + * Flash. The erase operation will result in an error if the block is + * locked. + */ + if ((FlashInstance.CommandSet == XFL_CMDSET_INTEL_STANDARD) || + (FlashInstance.CommandSet == XFL_CMDSET_INTEL_EXTENDED)) { + Status = XFlash_Unlock(&FlashInstance, BLOCK_OFFSET_ADDR, 0); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + + /* + * Perform the Erase operation. + */ + Status = XFlash_Erase(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Prepare the write buffer. Fill in the data need to be written into + * Flash Device. + */ + for(Index = 0; Index < FLASH_TEST_SIZE; Index++) { + WriteBuffer[Index] = Index + 1; + } + + /* + * Perform the Write operation. + */ + Status = XFlash_Write(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE, + WriteBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform the read operation. + */ + Status = XFlash_Read(&FlashInstance, START_ADDRESS, FLASH_TEST_SIZE, + ReadBuffer); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Compare the data read against the data Written. + */ + for(Index = 0; Index < FLASH_TEST_SIZE; Index++) { + if(ReadBuffer[Index] != WriteBuffer[Index]) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilflash/src/Makefile b/lib/sw_services/xilflash/src/Makefile new file mode 100644 index 00000000..f6d01a65 --- /dev/null +++ b/lib/sw_services/xilflash/src/Makefile @@ -0,0 +1,88 @@ +############################################################################### +# +# Copyright (C) 2007 - 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. +# +############################################################################### + +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} +ISF_DIR = . + +EXPORT_INCLUDE_FILES = $(ISF_DIR)/include/xilflash.h \ + $(ISF_DIR)/include/xilflash_cfi.h \ + $(ISF_DIR)/include/xilflash_intel.h \ + $(ISF_DIR)/include/xilflash_properties.h \ + $(ISF_DIR)/include/xilflash_amd.h + +LIB_SRCS = $(ISF_DIR)/xilflash.c \ + $(ISF_DIR)/xilflash_cfi.c \ + $(ISF_DIR)/xilflash_intel.c \ + $(ISF_DIR)/xilflash_amd.c + + +# create ISF_SRCS based on configured options + +ISF_SRCS = $(LIB_SRCS) + +ISF_OBJS = $(ISF_SRCS:%.c=%.o) + +libs: libxilflash.a + cp libxilflash.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 libxilflash.a + +libxilflash.a: obj_dir print_msg_flash_base $(ISF_OBJS) + @echo "Creating archive $@" + $(ARCHIVER) rc $@ obj/*.o + +obj_dir: + mkdir obj + +print_msg_flash_base: + @echo "Compiling XilFlash Library:" + +.c.o: + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) -c $< -o obj/$(@F) diff --git a/lib/sw_services/xilflash/src/include/xilflash.h b/lib/sw_services/xilflash/src/include/xilflash.h new file mode 100644 index 00000000..4378fea1 --- /dev/null +++ b/lib/sw_services/xilflash/src/include/xilflash.h @@ -0,0 +1,634 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash.h +* +* This module implements the functionality for flash memory devices that +* conform to the "Common Flash Interface" (CFI) standard. CFI allows a single +* flash library to be used for an entire family of parts. +* +* This is not a library for a specific device, but for a set of command +* read/write/erase algorithms. CFI allows us to determine which algorithm to +* utilize at runtime. +* +* Library Initialization +* +* The function call XFlash_Initialize() should be called by the application +* before any other function in the library. The initialization function checks +* for the device family and initializes the XFlash instance with the family +* specific data. The VT table (Contains the function pointers to family specific +* API's) is setup and family specific initialization routine is called. +* +* Device Geometry +* +* The Device geometry varies for different flash device families. The following +* list describes geometry of different flash device families: +* +* Intel Flash Device Geometry +* +* Flash memory space is segmented into areas called blocks. The size of +* each block is based on a power of 2. A region is defined as a contiguous +* set of blocks of the same size. Some parts have several regions while +* others have one. The arrangement of blocks and regions is refered to by +* this module as the part's geometry. Some Intel flash supports multiple +* banks on the same device. This library supports single and multiple bank +* flash devices. +* +* AMD Flash Device Geometry +* +* Flash memory space is segmented into areas called banks and further in +* to regions and blocks. The size of each block is based on a power of 2. +* A region is defined as a contiguous set of blocks of the same size. Some +* parts have several regions while others have one. A bank is defined as a +* contiguous set of blocks. The bank may contain blocks of different size. +* The arrangement of blocks, regions and banks is referred to by this +* module as the part's geometry. +* +* The cells within the part can be programmed from a logic 1 to a logic 0 +* and not the other way around. To change a cell back to a logic 1, the +* entire block containing that cell must be erased. When a block is erased +* all bytes contain the value 0xFF. The number of times a block can be +* erased is finite. Eventually the block will wear out and will no longer +* be capable of erasure. As of this writing, the typical flash block can +* be erased 100,000 or more times. +* +* Write Operation +* +* The write call can be used to write a minimum of zero bytes and a maximum +* entire flash. If the Offset Address specified to write is out of flash or if +* the number of bytes specified from the Offset address exceed flash boundaries +* an error is reported back to the user. The write is blocking in nature in that +* the control is returned back to user only after the write operation is +* completed successfully or an error is reported. +* +* Read Operation +* +* The read call can be used to read a minimum of zero bytes and maximum of +* entire flash. If the Offset Address specified to write is out of flash +* boundary an error is reported back to the user. The read function reads memory +* locations beyond Flash boundary. Care should be taken by the user to make sure +* that the Number of Bytes + Offset address is within the Flash address +* boundaries. The write is blocking in nature in that the control is returned +* back to user only after the read operation is completed successfully or an +* error is reported. +* +* Erase Operation +* +* The erase operations are provided to erase a Block in the Flash memory. The +* erase call is blocking in nature in that the control is returned back to user +* only after the erase operation is completed successfully or an error is +* reported. +* +* Sector Protection +* +* The Flash Device is divided into Blocks. Each Block can be protected +* individually from unwarranted writing/erasing. The Block locking can be +* achieved using XFlash_Lock() lock. All the memory locations from the Offset +* address specified will be locked. The block can be unlocked using +* XFlash_UnLock() call. All the Blocks which are previously locked will be +* unlocked. The Lock and Unlock calls are blocking in nature in that the control +* is returned back to user only after the operation is completed successfully or +* an error is reported. +* The AMD flash device requires high voltage on Reset pin to perform lock and +* unlock operation. User must provide this high voltage (As defined in +* datasheet) to reset pin before calling lock and unlock API for AMD flash +* devices. Lock and Unlock features are not tested for AMD flash device. +* +* Device Control +* +* Functionalities specific to a Flash Device Family are implemented as Device +* Control. +* +* The following are the Intel specific device control: +* - Retrieve the last error data. +* - Get Device geometry. +* - Get Device properties. +* - Set RYBY pin mode. +* - Set the Configuration register (Platform Flash only). + +* The following are the AMD specific device control: +* - Get Device geometry. +* - Get Device properties. +* - Erase Resume. +* - Erase Suspend. +* - Enter Extended Mode. +* - Exit Extended Mode. +* - Get Protection Status of Block Group. +* - Erase Chip. +* +* @note +* +* This library needs to know the type of EMC core (AXI or XPS) used to +* access the cfi flash, to map the correct APIs. This library should be used +* with the emc driver, v3_01_a and above, so that this information can be +* automatically obtained from the emc driver. +* +* 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, cache control, or HW write protection +* management must be satisfied by the layer above this library. +*

+* All writes to flash occur in units of bus-width bytes. If more than one part +* exists on the data bus, then the parts are written in parallel. Reads from +* flash are performed in any width up to the width of the data bus. It is +* assumed that the flash bus controller or local bus supports these types of +* accesses. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date      Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  10/25/07 First release
+* 1.00a mta  10/25/07 Updated to flash library
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 1.02a ksu  06/16/09 Added support for multiple banks in Intel flash
+*		      Removed unused defines (XFL_MAX_NUM_BANKS, XFL_BANK1,
+*		      XFL_BANK2)
+*		      Added IOCTL to set configuration register of platform
+*		      flash
+* 1.03a ksu  10/07/09 Added support for large buffer size flash (CR535564)
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 2.01a ktn  03/31/10 Updated the AMD code to support uniform sector WP modes
+* 2.02a sdm  06/30/10 Updated to support AXI EMC with Little Endian Processor
+* 2.02a sdm  07/07/10 Updated XFlashAmd_Initialize() to NOT change the erase
+*		      region information of a top boot device, when the number
+*		      of erase regions is not more than 1.
+* 3.00a sdm  03/03/11 Removed static parameters in mld and updated code to
+*		      determine these parameters from the CFI data.
+* 3.00a sdm  03/23/11 Added two new parameters in mld for flash families. Users
+*		      can enable support for either of the flash devices or both
+*		      of them.
+* 3.01a srt  03/02/12 Added support for Micron G18 Flash device to fix
+*		      CRs 648372, 648282.
+*		      Modified XFlashIntel_Reset function to reset all the
+*		      partitions.
+*		      Added DATA_SYNC to fix the CR 644750.
+* 3.02a srt  05/30/12 Changed Implementation for Micron G18 Flash, which
+*		      fixes the CR 662317.
+*		      CR 662317 Description - Xilinx Platform Flash on ML605
+*		      fails to work.
+* 3.03a srt  11/04/12 Increased AMD maximum erase regions (CR 668730)
+* 		      Fixed CR 679937  -
+*		      Description: Non-word aligned data write to flash fails
+*		      with AXI interface.
+* 3.04a srt  02/18/13 Fixed CR 700553.
+*
+* 
+* +***************************************************************************/ + +#ifndef XFLASH_H /* prevent circular inclusions */ +#define XFLASH_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xstatus.h" +#include "xilflash_properties.h" +#include "xparameters.h" +#include + +/************************** Constant Definitions *****************************/ + +/** + * Vendor command set codes. + * Refer to industry document "CFI publication 100" for the latest list + */ +#define XFL_CMDSET_INTEL_STANDARD 3 /**< Includes Micron/Sharp */ +#define XFL_CMDSET_INTEL_EXTENDED 1 /**< Includes Micron/Sharp */ +#define XFL_CMDSET_AMD_STANDARD 2 /**< Includes Fujitsu/STM */ +#define XFL_CMDSET_AMD_EXTENDED 4 /**< Includes Fujitsu/STM */ +#define XFL_CMDSET_MITSUBISHI_STANDARD 256 +#define XFL_CMDSET_MITSUBISHI_EXTENDED 257 +#define XFL_CMDSET_INTEL_G18 0x200 /**< Micron G18 Flash */ + +/* + * Flash return types. + */ +#define XFLASH_BUSY 101 /**< Flash is erasing or + * programming + */ +#define XFLASH_READY 102 /**< Flash is ready for + * commands + */ +#define XFLASH_ERROR 103 /**< Flash had detected an + * internal error. Use + * XFlash_DeviceControl + * to retrieve device specific + * codes + */ +#define XFLASH_ERASE_SUSPENDED 104 /**< Flash is in suspended erase + * state + */ +#define XFLASH_WRITE_SUSPENDED 105 /**< Flash is in suspended write + * state + */ +#define XFLASH_PART_NOT_SUPPORTED 106 /**< Flash type not supported by + * library + */ +#define XFLASH_NOT_SUPPORTED 107 /**< Operation not supported */ +#define XFLASH_TOO_MANY_REGIONS 108 /**< Too many erase regions */ +#define XFLASH_TIMEOUT_ERROR 109 /**< Programming or erase + * operation aborted due to a + * timeout + */ +#define XFLASH_ADDRESS_ERROR 110 /**< Accessed flash outside its + * addressable range + */ +#define XFLASH_ALIGNMENT_ERROR 111 /**< Write alignment error */ +#define XFLASH_BLOCKING_CALL_ERROR 112 /**< Couldn't return immediately + * from write/erase function + * with + * XFL_NON_BLOCKING_WRITE/ERASE + * option cleared + */ +#define XFLASH_CFI_QUERY_ERROR 113 /**< Failed to query the device + */ +#define XFLASH_BLOCK_PROTECTED 114 /**< Block is protected */ + +/** + * Supported part arrangements. + * This enumeration defines the supported arrangements of parts on the + * data-bus. The naming convention for these constants is as follows: + * + * XFL_LAYOUT_Xa_Xb_Xc, where + * + * Xa is the part's physical data bus width. Xb is the is the part's selected + * data bus width (this field is required because a x16 part can be placed in + * x8 mode). Xc is the number of interleaved parts. For example one part can + * be tied to D0-D15 and a second to data lines D15-D31. + * + * Parts arranged in series should be treated as separate instances. An example + * of this layout: Two X16 parts operating in X16 mode. The first part occupies + * address space FF000000 - FF0FFFFF and a second from FF100000 - FF1FFFFF. + * + * These constants are encoded using bit masks defined in the next section. + */ +#define XFL_LAYOUT_X16_X8_X1 0x02020101 /**< One 16-bit part operating + * in 8-bit mode. Total data bus + * width is 8-bits. This layout + * is only supported in AMD + * flash devices + */ +#define XFL_LAYOUT_X16_X16_X1 0x02020201 /**< One 16-bit part operating + * in 16-bit mode. Total data + * bus width is 16-bits. This + * layout is supported in AMD + * and Intel flash devices + */ +#define XFL_LAYOUT_X16_X16_X2 0x04020202 /**< Two 16-bit parts operating + * in 16-bit mode. Total data + * bus width is 32-bits. This + * layout is only supported in + * Intel flash devices + */ +#define XFL_LAYOUT_X16_X16_X4 0x08020204 /**< Four 16-bit parts operating + * in 16-bit mode. Total data + * bus width is 64-bits. This + * layout is only supported in + * Intel flash devices + */ + +/* + * DeviceControl list for all family. + */ +#define XFL_DEVCTL_GET_LAST_ERROR 1 /**< Retrieve the last error + * data */ +#define XFL_DEVCTL_GET_GEOMETRY 2 /**< Get Device geometry */ +#define XFL_DEVCTL_GET_PROPERTIES 3 /**< Get Device Properties */ +#define XFL_DEVCTL_SET_RYBY 4 /**< Set RYBY pin mode */ +#define XFL_DEVCTL_ERASE_RESUME 5 /**< Resume Erase */ +#define XFL_DEVCTL_ERASE_SUSPEND 6 /**< Suspend Erase */ +#define XFL_DEVCTL_ENTER_EXT_MODE 7 /**< Enter Extended mode */ +#define XFL_DEVCTL_EXIT_EXT_MODE 8 /**< Exit Extended mode */ +#define XFL_DEVCTL_CHIP_ERASE 9 /**< Erase whole chip */ +#define XFL_DEVCTL_PROTECTION_STATUS 10 /**< Check block protection + * status */ +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL + #define XFL_DEVCTL_SET_CONFIG_REG 11 /**< Set config register value*/ +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ + +/** + * A block region is defined as a set of consecutive erase blocks of the + * same size. Most flash devices only have a handful of regions. If a + * part has more regions than defined by this constant, then the constant + * must be modified to accommodate the part. The minimum value of this + * constant is 1 and there is no maximum value. Note that increasing this + * value also increases the amount of memory used by the geometry structure + * approximately 12 bytes per increment. + */ +#define XFL_INTEL_MAX_ERASE_REGIONS 20 + +/* + * Maximum number of erase region and banks for AMD family. + */ +#define XFL_AMD_MAX_ERASE_REGIONS 10 + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL + #define XFL_MAX_ERASE_REGIONS XFL_INTEL_MAX_ERASE_REGIONS + #define XFL_MAX_VENDOR_DATA_LENGTH 20 /* Number of 32-bit integers + * reserved for vendor data + */ +#else + #define XFL_MAX_ERASE_REGIONS XFL_AMD_MAX_ERASE_REGIONS + #define XFL_MAX_VENDOR_DATA_LENGTH 10 /* Number of 32-bit integers + * reserved for vendor data + */ +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef contains configuration information for the device. + */ +typedef struct { + u32 BaseAddr; /**< Base address of array */ + u8 NumParts; /**< Number of parts in the array */ + u8 PartWidth; /**< Width of each part in bytes */ + u8 PartMode; /**< Operation mode of each part in bytes */ +} XFlash_UserInputs; + +/** + * Flash geometry + */ +typedef struct { + u32 BaseAddress; /**< Base address of part(s) */ + u32 MemoryLayout; /**< How multiple parts are connected on + * the data bus. Choices are limited to + * XFL_LAYOUT_Xa_Xb_Xc constants */ + u32 DeviceSize; /**< Total device size in bytes */ + u32 NumEraseRegions; /**< Number of erase regions */ + u16 NumBlocks; /**< Total number of blocks in device */ + u8 BootMode; + struct { + u32 AbsoluteOffset; /**< Offset within part where + * region begins */ + u16 AbsoluteBlock; + /**< Block number where region begins */ + u16 Number; /**< Number of blocks in this region */ + u32 Size; /**< Size of the block in bytes */ + } EraseRegion[XFL_MAX_ERASE_REGIONS + 1]; + +} XFlashGeometry; + +/* + * Define a type to contain part specific data to be maintained by + * the part component. Within the component, a new type is defined that + * overlays this type. + */ +typedef u32 XFlashVendorData[XFL_MAX_VENDOR_DATA_LENGTH]; + +/* + * Define a union that contains structures which represent the argument list of + * of various Device Control operations. + */ +typedef union { + + struct { + XFlashGeometry *GeometryPtr; + } GeometryParam; + + struct { + XFlashProperties *PropertiesPtr; + } PropertiesParam; + + struct { + u32 Param; + } RyByParam; + + struct { + u32 Error; + } LastErrorParam; + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL + struct { + u32 Value; + } ConfigRegParam; +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ +} DeviceCtrlParam; + +/** + * The XFlash library instance data. The user is required to allocate a + * variable of this type for every flash device in the system. A pointer + * to a variable of this type is then passed to the library API functions. + */ +typedef struct XFlashTag { + u32 Options; /* Current device options */ + int IsReady; /* Device is initialized and ready */ + int IsPlatformFlash; /* Indicates whether this a platform flash */ + u16 CommandSet; /* Command algorithm used by part. Choices + * are defined in XFL_CMDSET constants + */ + XFlashGeometry Geometry; /* Part geometry */ + XFlashProperties Properties; /* Part timing, programming, & + * identification properties + */ + XFlashVendorData VendorData; /* Part specific data */ + + + struct { + int (*Read) (struct XFlashTag * InstancePtr, u32 Offset, + u32 Bytes, void *DestPtr); + + int (*Write) (struct XFlashTag * InstancePtr, u32 Offset, + u32 Bytes, void *SrcPtr); + + int (*Erase) (struct XFlashTag * InstancePtr, u32 Offset, + u32 Bytes); + + int (*Lock) (struct XFlashTag * InstancePtr, u32 Offset, u32 + Bytes); + + int (*Unlock) (struct XFlashTag * InstancePtr, u32 Offset, u32 + Bytes); + + int (*EraseChip) (struct XFlashTag * InstancePtr); + + int (*Initialize) (struct XFlashTag * Initialize); + + int (*Reset) (struct XFlashTag * InstancePtr); + int (*DeviceControl) (struct XFlashTag * InstancePtr, + u32 Command, DeviceCtrlParam + *Parameters); + } VTable; + XFlashCommandSet Command; /* Flash Specific Commands */ +} XFlash; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* + * The following macros implement flash I/O primitives. All flash components + * use these macros to access the flash devices. The only exceptions are read + * functions which simply copy data using memcpy or equivalent utility funcs. + * The 8, 16, 32, 64 signify the access width. + */ +#define READ_FLASH_8(Address) (*(volatile u8*)(Address)) + +#define READ_FLASH_16(Address) (*(volatile u16*)(Address)) + +#define READ_FLASH_32(Address) (*(volatile u32*)(Address)) + +#define READ_FLASH_64(Address, Data) \ + (XUINT64_MSW(Data) = *(volatile u32*)(Address)); \ + (XUINT64_LSW(Data) = *(volatile u32*)(((u32)(Address) + 4))) + +#define WRITE_FLASH_8(Address, Data) (*(volatile u8*)(Address) = (u8)(Data)) + +#define WRITE_FLASH_16(Address, Data) (*(volatile u16*)(Address) = (u16)(Data)) + +#define WRITE_FLASH_32(Address, Data) (*(volatile u32*)(Address) = (u32)(Data)) + +#define WRITE_FLASH_64(Address, Data) \ + (*(volatile u32*)(Address) = XUINT64_MSW(Data)); \ + (*(volatile u32*)((u32)(Address) + 4) = XUINT64_LSW(Data)) + +#define WRITE_FLASH_64x2(Address, Data1, Data2) \ + (*(volatile u32*)(Address) = Data1); \ + (*(volatile u32*)((u32)(Address) + 4) = Data2) + +/*****************************************************************************/ +/** +* +* Increments the given Region and Block to the next block address. +* +* @param GeometryPtr is the geometry instance that defines flash +* addressing. +* @param Region is the starting region. +* @param Block is the starting block. +* +* @return Region parameter is incremented if the next block starts in a +* new region. Block parameter is set to zero if the next block +* starts in a new region, otherwise it is incremented by one. +* +*****************************************************************************/ +#define XFL_GEOMETRY_INCREMENT(GeometryPtr, Region, Block) \ +{ \ + if ((GeometryPtr)->EraseRegion[Region].Number <= ++(Block)) \ + { \ + (Region)++; \ + (Block) = 0; \ + } \ +} + +/*****************************************************************************/ +/** +* +* Calculates the number of blocks between the given start and end coordinates. +* +* @param GeometryPtr is the geometry instance that defines flash +* addressing. +* @param StartRegion is the starting region. +* @param StartBlock is the starting block. +* @param EndRegion is the ending region. +* @param EndBlock is the ending block. +* +* @return The number of blocks between start Region/Block and end +* Region/Block(inclusive). +* +*****************************************************************************/ +#define XFL_GEOMETRY_BLOCK_DIFF(GeometryPtr, StartRegion, StartBlock, \ + EndRegion,EndBlock) \ + (((GeometryPtr)->EraseRegion[EndRegion].AbsoluteBlock + (EndBlock)) - \ + ((GeometryPtr)->EraseRegion[StartRegion].AbsoluteBlock + \ + (StartBlock)) + 1) + +/*****************************************************************************/ +/** +* +* Tests the given absolute Offset to verify it lies within the bounds of the +* address space defined by a geometry instance. +* +* @param GeometryPtr is the geometry instance that defines flash +* addressing. +* @param Offset is the offset to test. +* +* @return +* - 0 if Offset do not lie within the address space described by +* GeometryPtr. +* - 1 if Offset are within the address space. +* +*****************************************************************************/ +#define XFL_GEOMETRY_IS_ABSOLUTE_VALID(GeometryPtr, Offset) \ + ((Offset) < (GeometryPtr)->DeviceSize) + +/*****************************************************************************/ +/** +* +* Tests the given Region, Block, and Offset to verify they lie within the +* address space defined by a geometry instance. +* +* @param GeometryPtr is the geometry instance that defines flash +* addressing +* @param Region is the region to test +* @param Block is the block to test +* @param BlockOffset is the offset within block +* +* @return +* - 0 if Region, Block, & BlockOffset do not lie within the +* address space described by GeometryPtr. +* - 1 if Region, Block, & BlockOffset are within the address space +* +*****************************************************************************/ +#define XFL_GEOMETRY_IS_BLOCK_VALID(GeometryPtr, Region, Block, BlockOffset) \ + (((Region) < ( GeometryPtr)->NumEraseRegions) && \ + ((Block) < (GeometryPtr)->EraseRegion[Region].Number) && \ + ((BlockOffset) < (GeometryPtr)->EraseRegion[Region].Size)) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization, configuration, & control Functions. + */ +int XFlash_Initialize(XFlash * InstancePtr, u32 BaseAddress, u8 BusWidth, + int IsPlatformFlash); +int XFlash_Reset(XFlash * InstancePtr); +int XFlash_DeviceControl(XFlash * InstancePtr, u32 Command, + DeviceCtrlParam *Parameters); +int XFlash_Read(XFlash * InstancePtr, u32 Offset, u32 Bytes, void *DestPtr); +int XFlash_Write(XFlash * InstancePtr, u32 Offset, u32 Bytes, void *SrcPtr); +int XFlash_Erase(XFlash * InstancePtr, u32 Offset, u32 Bytes); +int XFlash_Lock(XFlash * InstancePtr, u32 Offset, u32 Bytes); +int XFlash_Unlock(XFlash * InstancePtr, u32 Offset, u32 Bytes); +int XFlash_IsReady(XFlash * InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilflash/src/include/xilflash_amd.h b/lib/sw_services/xilflash/src/include/xilflash_amd.h new file mode 100644 index 00000000..3a6e245e --- /dev/null +++ b/lib/sw_services/xilflash/src/include/xilflash_amd.h @@ -0,0 +1,157 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_amd.h +* +* This file consists definitions, Macros and structures specific to the AMD +* flash devices. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.01a ksu  04/10/08 First Release.
+* 2.01a ktn  03/31/10 Updated the AMD code to support uniform sector WP modes.
+*		      Addded the new definitions XFL_AMD_TOP_WP_UNIFORM and
+*		      XFL_AMD_BOTTOM_WP_UNIFORM.
+* 
+* +******************************************************************************/ + +#ifndef XFLASH_AMD_H /* prevent circular inclusions */ +#define XFLASH_AMD_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#ifdef XPAR_XFL_DEVICE_FAMILY_AMD +#include "xilflash.h" + +/************************** Constant Definitions *****************************/ + +/* + * The following constant defines address of addresses to be sent on address bus + * when sending command on data bus. + */ +#define XFL_AMD_CMD1_ADDR (0x0555) +#define XFL_AMD_CMD2_ADDR (0x02AA) + +/* + * The following constant defines data to be sent on data bus when sending + * command on data bus. + */ +#define XFL_AMD_CMD1_DATA (0x00AA) +#define XFL_AMD_CMD2_DATA (0x0055) + +/* + * The following constant defines command set of AMD flash family. + */ +#define XFL_AMD_CMD_RESET (0x00F0) /* Reset or read mode */ +#define XFL_AMD_CMD_AUTO_SELECT (0x0090) /* Auto select command */ +#define XFL_AMD_CMD_ERASE_RESUME (0x0030) /* Resume erase */ +#define XFL_AMD_CMD_ERASE_SUSPEND (0x00B0) /* Suspend erase */ +#define XFL_AMD_CMD_ERASE1 (0x0080) /* Erase 1 command */ +#define XFL_AMD_CMD_ERASE_BLOCK (0x0030) /* Erase 2 command */ +#define XFL_AMD_CMD_UNLOCK_BYPASS (0x0020) /* Unlock bypass command */ +#define XFL_AMD_CMD_PROGRAM (0x00A0) /* Program command */ +#define XFL_AMD_CMD_UNLOCK_BYPASS_RESET1 (0x0090) /* Unlock bypass 1 command */ +#define XFL_AMD_CMD_UNLOCK_BYPASS_RESET2 (0x0000) /* Unlock bypass 1 command */ +#define XFL_AMD_CMD_ERASE_CHIP (0x0010) /* Chip erase command */ +#define XFL_AMD_CMD_ENTER_EXT_MODE (0x0088) /* Enter extended mode */ +#define XFL_AMD_CMD_EXIT_EXT_MODE (0x0090) /* Enter extended mode */ +#define XFL_AMD_CMD_GROUP_PROTECT1 (0x0060) /* Group protect command */ +#define XFL_AMD_CMD_GROUP_PROTECT2 (0x0040) /* Group protect command */ + +/* + * The following constant defines command set of AMD flash family. + */ +#define XFL_AMD_SR_ERASE_START_MASK (0x0008) /* Erase start mask */ +#define XFL_AMD_SR_ERASE_COMPL_MASK (0x0040) /* Erase operation completed + * mask */ +#define XFL_AMD_SR_ERASE_ERROR_MASK (0x0020) /* Alternate erase operation + * completed mask */ + +#define XFL_AMD_TOP_BOOT (0x03) /* Top boot device */ +#define XFL_AMD_BOTTOM_BOOT (0x02) /* Bottom boot device */ +#define XFL_AMD_TOP_WP_UNIFORM (0x05) /* Top WP uniform sectors */ +#define XFL_AMD_BOTTOM_UNIFORM (0x04) /* Bottom WP uniform sectors */ + +#define XFL_MAX_BANKS (0x0002) /* Number of banks */ +#define XFL_AMD_MANUFECTURE_ID_OFFSET (0x0000) /* Manufacture ID offset + * when reading status */ +#define XFL_AMD_PROT_STATUS_OFFSET (0x0002) /* Protection status offset + * when reading status */ +#define XFL_AMD_GROUP_UNPROTECTED (0x0000) /* Block is not protected */ +#define XFL_AMD_GROUP_PROTECTED (0x0001) /* Block is protected */ +#define XFL_AMD_CHIP_UNPROTECT_ADDR (0x042) /* Chip unprotect address bits + */ +#define XFL_COUNT_FOR_A_MICROSECOND (63) /* Number of clock pulse for 1 + * micro second */ +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +int XFlashAmd_Initialize(XFlash * InstancePtr); +int XFlashAmd_Reset(XFlash * InstancePtr); + +int XFlashAmd_DeviceControl(XFlash * InstancePtr, u32 Command, + DeviceCtrlParam *Parameters); + +int XFlashAmd_Read(XFlash * InstancePtr, u32 Offset, u32 Bytes, + void *DestPtr); + +int XFlashAmd_Write(XFlash * InstancePtr, u32 Offset, u32 Bytes, + void *SrcPtr); + +int XFlashAmd_Erase(XFlash * InstancePtr, u32 Offset, u32 Bytes); + +int XFlashAmd_Lock(XFlash * InstancePtr, u32 Offset, u32 Bytes); +int XFlashAmd_Unlock(XFlash * InstancePtr, u32 Offset, u32 Bytes); +int XFlashAmd_EraseChip(struct XFlashTag * InstancePtr); + +#endif /* XPAR_XFL_DEVICE_FAMILY_AMD */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilflash/src/include/xilflash_cfi.h b/lib/sw_services/xilflash/src/include/xilflash_cfi.h new file mode 100644 index 00000000..731338a2 --- /dev/null +++ b/lib/sw_services/xilflash/src/include/xilflash_cfi.h @@ -0,0 +1,156 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_cfi.h +* +* This file contains methods used to extract and interpret Common Flash +* Interface(CFI) from a flash memory part that supports the CFI query command. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  10/25/07 First release
+* 1.00a mta  10/25/07 Updated to flash library
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 
+* +***************************************************************************/ + +#ifndef XFLASH_CFI_H /* prevent circular inclusions */ +#define XFLASH_CFI_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xstatus.h" +#include "xilflash.h" +#include "xilflash_properties.h" +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL + #include "xilflash_intel.h" +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ +#ifdef XPAR_XFL_DEVICE_FAMILY_AMD + #include "xilflash_amd.h" +#endif /* XPAR_XFL_DEVICE_FAMILY_AMD */ +/************************** Constant Definitions *****************************/ + +/** + * LAYOUT constants are used to parse the XFL_LAYOUT_X* constants. + */ +#define XFL_LAYOUT_NUM_PARTS_MASK 0x000000FF +#define XFL_LAYOUT_PART_MODE_MASK 0x0000FF00 +#define XFL_LAYOUT_PART_WIDTH_MASK 0x00FF0000 +#define XFL_LAYOUT_CFI_INTERL_MASK 0xFF000000 + +#define XFL_LAYOUT_NUM_PARTS_1 0x00000001 +#define XFL_LAYOUT_NUM_PARTS_2 0x00000002 +#define XFL_LAYOUT_NUM_PARTS_4 0x00000004 +#define XFL_LAYOUT_PART_MODE_8 0x00000100 +#define XFL_LAYOUT_PART_MODE_16 0x00000200 +#define XFL_LAYOUT_PART_WIDTH_8 0x00010000 +#define XFL_LAYOUT_PART_WIDTH_16 0x00020000 +#define XFL_LAYOUT_CFI_INTERL_1 0x01000000 +#define XFL_LAYOUT_CFI_INTERL_2 0x02000000 +#define XFL_LAYOUT_CFI_INTERL_4 0x04000000 +#define XFL_LAYOUT_CFI_INTERL_8 0x08000000 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +/*****************************************************************************/ +/** +* +* Moves the CFI data pointer to a physical address that corresponds to a +* specific CFI byte offset. +* +* @param Ptr is the pointer to modify. Can be of any type. +* @param BaseAddr is the base address of flash part. +* @param Interleave is the byte interleaving (based on part layout). +* @param ByteAddr is the byte offset within CFI data to read. +* +* @return The Ptr argument is set to point at the CFI byte specified +* by the ByteAddr parameter. +* +*****************************************************************************/ +#define XFL_CFI_POSITION_PTR(Ptr, BaseAddr, Interleave, ByteAddr) \ +( \ + Ptr = (void*)((u32)BaseAddr + ((u32)Interleave * \ + (u32)ByteAddr)) \ +) + +/*****************************************************************************/ +/** +* +* Advances the CFI pointer to the next byte. +* +* @param Ptr is the pointer to advance. Can be a pointer to any type. +* @param Interleave is the byte interleaving (based on part layout). +* +* @return Adjusted Ptr. +* +*****************************************************************************/ +#define XFL_CFI_ADVANCE_PTR8(Ptr, Interleave) \ + (Ptr = (void*)((u32)Ptr + (Interleave))) + +/*****************************************************************************/ +/** +* +* Advances the CFI pointer to the next 16-bit quantity. +* +* @param Ptr is the pointer to advance. Can be a pointer to any type. +* @param Interleave is the byte interleaving (based on part layout). +* +* @return Adjusted Ptr. +* +*****************************************************************************/ +#define XFL_CFI_ADVANCE_PTR16(Ptr, Interleave) \ + (Ptr = (void*)((u32)Ptr + ((Interleave) << 1))) + + +/************************** Function Prototypes ******************************/ + +int XFlashCFI_ReadCommon(XFlash *InstancePtr, u8 BusWidth); +int XFlashCFI_Read8(u8 *Ptr, u8 Interleave, u8 Mode); +int XFlashCFI_Read16(u8 *Ptr, u8 Interleave, u8 Mode); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilflash/src/include/xilflash_intel.h b/lib/sw_services/xilflash/src/include/xilflash_intel.h new file mode 100644 index 00000000..40482672 --- /dev/null +++ b/lib/sw_services/xilflash/src/include/xilflash_intel.h @@ -0,0 +1,280 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_intel.h +* +* This file consists definitions, Macros and structures specific to the Intel +* flash devices. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  10/25/07 First release
+* 1.00a mta  10/25/07 Updated to flash library
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 1.02a ksu  06/16/09 Added support for multiple banks in Intel flash.
+*                     Added Reset Bank function.
+*                     Added support for 0xF0 reset command.
+*                     Added XFL_DEVCTL_SET_CONFIG_REG IOCTL to write to the
+*                     Configuration Register of the Xilinx Platform Flash XL
+*                     which can be used to set the Flash in Sync/Async mode.
+*                     The Xilinx Platform Flash XL is set to Async mode during
+*                     the initialization of the library.
+*                     Added bank(s) reset function at the top of the read
+*                     function.
+*                     Updated Lock and Unlock operations for multiple blocks.
+* 3.01a srt  03/02/12 Added support for Micron G18 Flash device to fix
+*		      CRs 648372, 648282.
+* 3.02a srt  05/30/12 Changed Implementation for Micron G18 Flash, which
+*		      fixes the CR 662317.
+*		      CR 662317 Description - Xilinx Platform Flash on ML605
+*		      fails to work.
+*
+* 
+* +******************************************************************************/ + +#ifndef XFLASH_INTEL_H /* prevent circular inclusions */ +#define XFLASH_INTEL_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL +#include "xilflash.h" + +/************************** Constant Definitions *****************************/ + +/** + * Supported manufacturer IDs. Note, that not all parts from these listed + * vendors are supported. + */ +#define XFL_MANUFACTURER_ID_INTEL 0x89 + +/** + * RYBY Options + * These options control the RYBY signal. They can be accessed with the + * XFL_INTEL_DEVCTL_SET_RYBY command. + */ +#define XFL_INTEL_RYBY_PULSE_OFF 0 /* Do not pulse */ +#define XFL_INTEL_RYBY_PULSE_ON_ERASE 1 /* Pulse on erase + * complete only */ +#define XFL_INTEL_RYBY_PULSE_ON_PROG 2 /* Pulse on program + * complete only */ +#define XFL_INTEL_RYBY_PULSE_ON_ERASE_PROG 3 /* Pulse on erase & + * program complete */ + +/* + * Status register bit definitions. Use these bitmaps to decipher the + * return value of the XFL_INTEL_DEVCTL_GET_LAST_ERROR command. + */ +#define XFL_INTEL_SR_WSM_READY 0x80 +#define XFL_INTEL_SR_ERASE_SUSPENDED 0x40 +#define XFL_INTEL_SR_ERASE_OR_UNLOCK_ERROR 0x20 +#define XFL_INTEL_SR_PROG_OR_LOCK_ERROR 0x10 +#define XFL_INTEL_SR_VOLTAGE_ERROR 0x08 +#define XFL_INTEL_SR_WRITE_SUSPENDED 0x04 +#define XFL_INTEL_SR_BLOCK_LOCKED_ERROR 0x02 + +/***************************************************************************** +* +* Extended capabilities list +* These bits can be read with the XFL_INTEL_DEVCTL_GET_SUPPORT1 command. +* +* XFL_INTEL_SUPPORT1_CHIP_ERASE - The part supports the chip erase command. +* +* XFL_INTEL_SUPPORT1_SUSPEND_ERASE - The part supports suspension and +* resumption of an erase operation. +* +* XFL_INTEL_SUPPORT1_SUSPEND_PROG - The part supports suspension and +* resumption of a programming operation. +* +* XFL_INTEL_SUPPORT1_LEGACY_LOCK - The part supports legacy lock/unlock. +* +* XFL_INTEL_SUPPORT1_QUEUED_ERASE - The part supports the queuing up of +* erase blocks. +* +* XFL_INTEL_SUPPORT1_INSTANT_LOCK - The part supports instant individual +* block locking. +* +* XFL_INTEL_SUPPORT1_PROTECTION_BIT - The part supports protection bits. +* +* XFL_INTEL_SUPPORT1_PAGE_MODE_READ - The part supports page-mode reads. +* +* XFL_INTEL_SUPPORT1_SYNC_READ - The part supports synchronous reads. +* +*****************************************************************************/ +#define XFL_INTEL_SUPPORT1_CHIP_ERASE 0x80000000 +#define XFL_INTEL_SUPPORT1_SUSPEND_ERASE 0x40000000 +#define XFL_INTEL_SUPPORT1_SUSPEND_PROG 0x20000000 +#define XFL_INTEL_SUPPORT1_LEGACY_LOCK 0x10000000 +#define XFL_INTEL_SUPPORT1_QUEUED_ERASE 0x08000000 +#define XFL_INTEL_SUPPORT1_INSTANT_LOCK 0x04000000 +#define XFL_INTEL_SUPPORT1_PROTECTION_BIT 0x02000000 +#define XFL_INTEL_SUPPORT1_PAGE_MODE_READ 0x01000000 +#define XFL_INTEL_SUPPORT1_SYNC_READ 0x00800000 + +/* + * Suspension capabilities list. + * + * XFL_INTEL_PROG_AFTER_ERASE_SUSPEND - The part supports programming + * after suspending an erase operation. + */ +#define XFL_INTEL_SUSPEND_SUPPORT_PROG_AFTER_ERASE 0x00000001 + +/* + * Commands written to the devices are defined by the CMD_* constants below. + * Each Command contains 8-bits of significant data. For x16 or greater devices, + * the command data should appear on the LSB. Other bytes may be written as + * don't cares. To eliminate the need to know the bus layout, the width of + * individual parts, or potential byte-swapping requirements, the CMD_* + * constants are defined with the command data in every nibble. + */ + +/* + * BCS/SCS command codes. + */ +#define XFL_INTEL_CMD_READ_ARRAY 0xFFFFFFFF +#define XFL_INTEL_CMD_READ_ID_CODES 0x90909090 +#define XFL_INTEL_CMD_READ_STATUS_REG 0x70707070 +#define XFL_INTEL_CMD_CLEAR_STATUS_REG 0x50505050 +#define XFL_INTEL_CMD_WRITE_BUFFER 0xE8E8E8E8 +#define XFL_INTEL_CMD_PROGRAM 0x40404040 +#define XFL_INTEL_CMD_BLOCK_ERASE 0x20202020 +#define XFL_INTEL_CMD_CONFIRM 0xD0D0D0D0 +#define XFL_INTEL_CMD_SUSPEND 0xB0B0B0B0 +#define XFL_INTEL_CMD_RESUME 0xD0D0D0D0 +#define XFL_INTEL_CMD_RESET_0xF0 0xF0F0F0F0 + +#define XFL_INTEL_STATUS_READY 0x00800080 + +/* + * SCS command codes. + */ +#define XFL_INTEL_CMD_READ_QUERY 0x98989898 +#define XFL_INTEL_CMD_CONFIG 0xB8B8B8B8 +#define XFL_INTEL_CMD_LOCK_BLOCK_SET 0x60606060 +#define XFL_INTEL_CMD_LOCK_BLOCK_SET_CONFIRM 0x01010101 +#define XFL_INTEL_CMD_LOCK_BLOCK_CLEAR 0x60606060 +#define XFL_INTEL_CMD_LOCK_BLOCK_CLEAR_CONFIRM 0xD0D0D0D0 +#define XFL_INTEL_CMD_CONFIG_REG_SETUP 0x60606060 +#define XFL_INTEL_CMD_CONFIG_REG_CONFIRM 0x03030303 + +/* + * Other command codes. + */ +#define XFL_INTEL_CMD_PROTECTION 0xC0C0C0C0 + +/* + * Configuration command codes. + */ +#define XFL_INTEL_CONFIG_RYBY_LEVEL 0x00000000 +#define XFL_INTEL_CONFIG_RYBY_PULSE_ERASE 0x01010101 +#define XFL_INTEL_CONFIG_RYBY_PULSE_WRITE 0x02020202 +#define XFL_INTEL_CONFIG_RYBY_PULSE_ALL 0x03030303 + +/* + * Configuration register value/address for setting sync and async mode of the + * platform flash. + * To put the memory in Asynchronous Read Mode, the CR15 bit of Configuration + * Register is set to 1. Rest of the Configuration Register Bits are set to + * default values. The Synchronous Read Mode is set by default with CR15 = 0. + * The commands to set Configuration register are "Set Configuration Register + * SetUP" (BASE_ADDR + CONFIG_REG_ASYNC_ADDR -> 0x0060) and "Set Configuration + * Register Confirm" (BASE_ADDR + CONFIG_REG_ASYNC_ADDR -> 0x0003). + * The Platform flash is 16 bit flash so the flash controller drop off the least + * significant bit of the address bus. So the Configuration register value seen + * at the flash device should be left shifted by 1. + */ +#define XFL_INTEL_CMD_CONFIG_REG_ASYNC_ADDR 0x17BBE +#define XFL_INTEL_CMD_CONFIG_REG_SYNC_ADDR 0x07BBE + +/* + * The Platform flash Manufacture ID and Device ID. + */ +#define XFL_INTEL_PLATFORM_MANUFACTURE_ID 0x0049 +#define XFL_INTEL_PLATFORM_DEVICE_ID 0x506B + +/* + * Micron StrataFlash Memory Device G18 + * (Partially compatible with Intel CFI) + */ +#define XFL_INTEL_G18_CMD_WRITE_BUFFER 0xE9E9E9E9 +#define XFL_INTEL_G18_CMD_PROGRAM 0x41414141 + + +/**************************** Type Definitions *******************************/ + +typedef struct { + XFlashGeometry Geometry; /* Part geometry */ + XFlashProperties Properties; /* Part timing, programming and + * identification properties */ + XFlashVendorData VendorData; /* Part specific data */ +} XFlashIntel_Device; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +int XFlashIntel_Initialize(XFlash * InstancePtr); +int XFlashIntel_Reset(XFlash * InstancePtr); + +int XFlashIntel_DeviceControl(XFlash * InstancePtr, u32 Command, + DeviceCtrlParam *Parameters); + +int XFlashIntel_Read(XFlash * InstancePtr, u32 Offset, u32 Bytes, + void *DestPtr); + +int XFlashIntel_Write(XFlash * InstancePtr, u32 Offset, u32 Bytes, + void *SrcPtr); + +int XFlashIntel_Erase(XFlash * InstancePtr, u32 Offset, u32 Bytes); + +int XFlashIntel_Lock(XFlash * InstancePtr, u32 Offset, u32 Bytes); +int XFlashIntel_Unlock(XFlash * InstancePtr, u32 Offset, u32 Bytes); +int XFlashIntel_GetStatus(XFlash * InstancePtr, u32 Offset); + +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilflash/src/include/xilflash_properties.h b/lib/sw_services/xilflash/src/include/xilflash_properties.h new file mode 100644 index 00000000..956cbbce --- /dev/null +++ b/lib/sw_services/xilflash/src/include/xilflash_properties.h @@ -0,0 +1,142 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_properties.h +* +* This file contains various data common to flash devices most of which can be +* derived from the CFI query. +* +* @note +* +* There is no implementation file with this component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  10/25/07 First release
+* 1.00a mta  10/25/07 Updated to flash library
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 1.02a ksu  06/16/09 Changed size of DeviceID in XFlashPartID structure
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 3.01a srt  03/02/12 Added support for Micron G18 Flash device to fix
+*		      CRs 648372, 648282.
+* 3.02a srt  05/30/12 Changed Implementation for Micron G18 Flash, which
+*		      fixes the CR 662317.
+*		      CR 662317 Description - Xilinx Platform Flash on ML605
+*		      fails to work.
+* 
+* +***************************************************************************/ + +#ifndef XFLASH_PROPERTIES_H /* prevent circular inclusions */ +#define XFLASH_PROPERTIES_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * Flash timing + */ +typedef struct { + u16 WriteSingle_Us; /**< Time to program a single word unit + * Units are in microseconds */ + u16 WriteBuffer_Us; /**< Time to program the contents of the + * write buffer. Units are in microseconds + * If the part does not support write + * buffers, then this value should be + * zero */ + u16 EraseBlock_Ms; /**< Time to erase a single block + * Units are in milliseconds */ + u16 EraseChip_Ms; /**< Time to perform a chip erase + * Units are in milliseconds */ +} XFlashTiming; + +/** + * Flash identification + */ +typedef struct { + u8 ManufacturerID; /**< Manufacturer of parts */ + u16 DeviceID; /**< Part number of manufacturer */ + u16 CommandSet; /**< Command algorithm used by part. Choices + * are defined in XFL_CMDSET constants */ +} XFlashPartID; + +/** + * Programming parameters + */ +typedef struct { + u32 WriteBufferSize; /**< Number of bytes that can be + * programmed at once */ + u32 WriteBufferAlignmentMask; /**< Alignment of the write buffer */ + u32 EraseQueueSize; /**< Number of erase blocks that can be + * queued up at once */ +} XFlashProgCap; + +/** + * Consolidated parameters + */ +typedef struct { + XFlashPartID PartID; /**< Uniquely identifies the part */ + XFlashTiming TimeTypical; /**< Typical timing data */ + XFlashTiming TimeMax; /**< Worst case timing data */ + XFlashProgCap ProgCap; /**< Programming capabilities */ +} XFlashProperties; + +/** + * Flash Specific Command Set + */ +typedef struct { + u32 WriteBufferCommand; + u32 ProgramCommand; +} XFlashCommandSet; + +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/lib/sw_services/xilflash/src/xilflash.c b/lib/sw_services/xilflash/src/xilflash.c new file mode 100644 index 00000000..0bb37037 --- /dev/null +++ b/lib/sw_services/xilflash/src/xilflash.c @@ -0,0 +1,682 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash.c +* +* This file contains the library functions to Initialize, Read, Write, Erase, +* Lock and Unlock the Parallel Flash Device. +* The family specific functionalities are implemented in DeviceControl API. +* Refer xilflash.h for detailed description. +* +* @note None +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  10/20/07 First release
+* 1.00a mta  10/25/07 Updated to flash library
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 1.02a ksu  06/16/09 Added support for multiple banks in Intel flash.
+*                     Added support for Xilinx Platform Flash XL. If the
+*                     user selects to use the Xilinx Platfrom Flash XL then
+*                     it is set to Async mode during the initialization.
+*                     If the user wants to use it in Sync mode then it can be
+*                     done using the XFlash_DeviceControl API.
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros.
+* 3.00a sdm  03/03/11 Removed static parameters in mld and updated code to
+*		      determine these parameters from the CFI data.
+* 3.01a srt  03/02/12 Added support for Micron G18 Flash device to fix
+*		      CRs 648372, 648282.
+* 3.02a srt  05/30/12 Changed Implementation for Micron G18 Flash, which
+*		      fixes the CR 662317.
+*		      CR 662317 Description - Xilinx Platform Flash on ML605
+*		      fails to work.
+* 
+* +* +****************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilflash.h" +#include "include/xilflash_cfi.h" +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL +#include "include/xilflash_intel.h" /* Intel specific header file */ +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ +#ifdef XPAR_XFL_DEVICE_FAMILY_AMD +#include "include/xilflash_amd.h" /* AMD specific header file */ +#endif /* XPAR_XFL_DEVICE_FAMILY_AMD */ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int SetVTable(XFlash * InstancePtr); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Initializes a specific XFlash instance. +* The initialization entails: +* - Check the Device family type. +* - Issuing the CFI query command. +* - Get and translate relevant CFI query information. +* - Set default options for the instance. +* - Setup the VTable. +* - Call the family initialize function of the instance. +* - Initialize the Xilinx Platform Flash XL to Async mode if the user +* selects to use the Platform Flash XL in the MLD. The Platform Flash XL +* is an Intel CFI complaint device. +* +* @param InstancePtr is a pointer to the XFlash instance. +* @param BaseAddress is the base address of the flash memory. +* @param BusWidth is the total width of the flash memory, in bytes. +* @param IsPlatformFlash is used to specify if the flash is a platform +* flash. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_PART_NOT_SUPPORTED if the command set algorithm or +* Layout is not supported by any flash family compiled into +* the system. +* - XFLASH_CFI_QUERY_ERROR if the device would not enter CFI +* query mode. Either the device(s) do not support CFI, the wrong +* BaseAddress param was used, an unsupported part layout exists, +* or a hardware problem exists with the part. +* +* @note BusWidth is not the width of an individual part. Its the total +* operating width. For example, if there are two 16-bit parts, +* with one tied to data lines D0-D15 and other tied to D15-D31, +* BusWidth would be (32 / 8) = 4. If a single 16-bit flash is in +* 8-bit mode, then BusWidth should be (8 / 8) = 1. +* +******************************************************************************/ +int XFlash_Initialize(XFlash * InstancePtr, u32 BaseAddress, u8 BusWidth, + int IsPlatformFlash) +{ + int Status = XST_FAILURE; + + /* + * Validate parameters. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if (BusWidth > 8) { + return XFLASH_PART_NOT_SUPPORTED; + } + + InstancePtr->IsReady = 0; + InstancePtr->Geometry.BaseAddress = BaseAddress; + InstancePtr->IsPlatformFlash = IsPlatformFlash; + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL + if (IsPlatformFlash == 1) { + /* + * Set Async mode for platform flash + */ + WRITE_FLASH_16(InstancePtr->Geometry.BaseAddress + + XFL_INTEL_CMD_CONFIG_REG_ASYNC_ADDR, + XFL_INTEL_CMD_CONFIG_REG_SETUP); + WRITE_FLASH_16(InstancePtr->Geometry.BaseAddress + + XFL_INTEL_CMD_CONFIG_REG_ASYNC_ADDR, + XFL_INTEL_CMD_CONFIG_REG_CONFIRM); + } +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ + + /* + * Get CFI data. + */ + Status = XFlashCFI_ReadCommon(InstancePtr, BusWidth); + if (Status != XST_SUCCESS) { + return (XFLASH_CFI_QUERY_ERROR); + } + + /* + * Set the VTable function pointer based on the command set algorithm + * discovered in the CFI query. + */ + Status = SetVTable(InstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Initialize the specific flash family device. + * If it initializes successfully set the IsReady flag to indicate the + * device is ready. + */ + Status = InstancePtr->VTable.Initialize(InstancePtr); + if (Status == XST_SUCCESS) { + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function reads the data from the Flash device and copies it into the +* specified user buffer. The source and destination addresses can be on any +* alignment supported by the processor. +* +* The device is polled until an error or the operation completes successfully. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from +* which to read. +* @param Bytes is the number of bytes to copy. +* @param DestPtr is the destination address to copy data to. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the source address does not start +* within the addressable areas of the device(s). +* +* @note This function allows the transfer of data past the end of the +* device's address space. If this occurs, then results are +* undefined. +* +******************************************************************************/ +int XFlash_Read(XFlash * InstancePtr, u32 Offset, u32 Bytes, void *DestPtr) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + return XST_FAILURE; + } + + return (InstancePtr->VTable.Read(InstancePtr, Offset, Bytes, DestPtr)); +} + +/*****************************************************************************/ +/** +* +* This function programs the flash device(s) with data specified in the user +* buffer. The source and destination address must be aligned to the width of the +* flash's data bus. +* +* The device is polled until an error or the operation completes successfully. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin programming. Must be aligned to the width of the +* flash's data bus. +* @param Bytes is the number of bytes to program. +* @param SrcPtr is the source address containing data to be programmed. +* Must be aligned to the width of the flash's data bus. +* The SrcPtr doesn't have to be aligned to the flash width if the +* processor supports unaligned access. But, since this library is +* generic, and some processors (eg. Microblaze) do not support +* unaligned access; this API requires the SrcPtr to be aligned. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. Use XFlash_DeviceControl() to +* retrieve specific error conditions. When this error is +* returned, it is possible that the target address range was +* only partially programmed. +* +* @note None. +* +******************************************************************************/ +int XFlash_Write(XFlash * InstancePtr, u32 Offset, u32 Bytes, void *SrcPtr) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + return XST_FAILURE; + } + + return (InstancePtr->VTable.Write(InstancePtr, Offset, Bytes, SrcPtr)); +} + +/*****************************************************************************/ +/** +* +* This function erases the specified address range in the flash device. The +* number of bytes to erase can be any number as long as it is within the bounds +* of the device(s). +* +* The device is polled until an error or the operation completes successfully. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin erasure. +* @param Bytes is the number of bytes to erase. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* +* @note Due to flash memory design, the range actually erased may be +* larger than what was specified by the Offset & Bytes parameters. +* This will occur if the parameters do not align to block +* boundaries. +* +******************************************************************************/ +int XFlash_Erase(XFlash * InstancePtr, u32 Offset, u32 Bytes) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + return XST_FAILURE; + } + + return (InstancePtr->VTable.Erase(InstancePtr, Offset, Bytes)); +} + +/*****************************************************************************/ +/** +* +* This function Locks the blocks in the specified range of the flash device(s). +* +* The device is polled until an error or the operation completes successfully. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin block locking. The first three bytes of every block is +* reserved for special purpose. The offset should be atleast three +* bytes from start of the block. +* @param Bytes indicates the number of bytes to Lock in the Block +* starting from Offset. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* +* @note Due to flash memory design, the range actually locked may be +* larger than what was specified by the Offset & Bytes parameters. +* This will occur if the parameters do not align to block +* boundaries. +* +******************************************************************************/ +int XFlash_Lock(XFlash * InstancePtr, u32 Offset, u32 Bytes) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + return XST_FAILURE; + } + + return (InstancePtr->VTable.Lock(InstancePtr, Offset, Bytes)); +} + +/*****************************************************************************/ +/** +* +* This function Unlocks the blocks in the specified range of the flash +* device(s). +* +* The device is polled until an error or the operation completes successfully. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin block UnLocking. The first three bytes of every block +* is reserved for special purpose. The offset should be atleast +* three bytes from start of the block. +* @param Bytes indicates the number of bytes to UnLock in the Block +* starting from Offset. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlash_Unlock(XFlash * InstancePtr, u32 Offset, u32 Bytes) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + return XST_FAILURE; + } + + return (InstancePtr->VTable.Unlock(InstancePtr, Offset, Bytes)); +} + +/*****************************************************************************/ +/** +* +* This function resets the flash device and places it in read mode. +* +* @param InstancePtr is the pointer to the XFlash instance. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_BUSY if the flash devices were in the middle of an +* operation and could not be reset. +* - XFLASH_ERROR if the device(s) have experienced an internal +* error during the operation. XFlash_DeviceControl() must be +* used to access the cause of the device specific error. +* condition. +* +* @note None. +* +******************************************************************************/ +int XFlash_Reset(XFlash * InstancePtr) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + return XST_FAILURE; + } + + return (InstancePtr->VTable.Reset(InstancePtr)); +} + +/*****************************************************************************/ +/** +* +* This function is used to execute device specific commands. +* For a list of device specific commands, see the xilflash.h. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Command is the device specific command to issue. +* @param Parameters specifies the arguments passed to the device control +* function. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_NOT_SUPPORTED if the command is not +* recognized/supported by the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlash_DeviceControl(XFlash * InstancePtr, u32 Command, + DeviceCtrlParam *Parameters) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) { + return XST_FAILURE; + } + + return (InstancePtr->VTable.DeviceControl(InstancePtr, Command, + Parameters)); +} + +/*****************************************************************************/ +/** +* +* Checks the readiness of the device, which means it has been successfully +* initialized. +* +* @param InstancePtr is a pointer to the XFlash instance. +* +* @return TRUE if the device has been initialized (but not necessarily +* started), and FALSE otherwise. +* +* @note None. +* +******************************************************************************/ +int XFlash_IsReady(XFlash * InstancePtr) +{ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + return (InstancePtr->IsReady == XIL_COMPONENT_IS_READY); +} + +/*****************************************************************************/ +/** +* +* Converts block coordinates to a part offset. Region, Block, & BlockOffset +* are converted to PartOffset +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Region is the erase region the physical address appears in. +* @param Block is the block within Region the physical address appears +* in. +* @param BlockOffset is the offset within Block where the physical +* address appears. +* @param AbsoluteOffsetPtr is the returned offset value. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the block coordinates are +* invalid. +* +* @note None. +* +******************************************************************************/ +int XFlashGeometry_ToAbsolute(XFlashGeometry * InstancePtr, + u16 Region, u16 Block,u32 BlockOffset, + u32 *AbsoluteOffsetPtr) +{ + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(AbsoluteOffsetPtr == NULL) { + return XST_FAILURE; + } + + /* + * Validate Region, Block, and BlockOffset parameters. + */ + if (!XFL_GEOMETRY_IS_BLOCK_VALID(InstancePtr, Region, Block, + BlockOffset)) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Calculate offset. + */ + *AbsoluteOffsetPtr = InstancePtr->EraseRegion[Region].AbsoluteOffset + + (InstancePtr->EraseRegion[Region].Size * Block) + BlockOffset; + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Converts part offset block coordinates. PartOffset is converted to Region, +* Block & BlockOffset +* +* @param InstancePtr is the pointer to the XFlashGeometry. +* @param AbsoluteOffset is the offset within part to find block +* coordinates for. +* @param RegionPtr is the region that corresponds to AbsoluteOffset. +* This is a return parameter. +* @param BlockPtr is the block within Region that corresponds to +* AbsoluteOffset. This is a return parameter. +* @param BlockOffsetPtr is the offset within Block that corresponds +* to AbsoluteOffset. This is a return parameter. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the block coordinates are invalid. +* +* @note None. +* +******************************************************************************/ +int XFlashGeometry_ToBlock(XFlashGeometry * InstancePtr, + u32 AbsoluteOffset, u16 *RegionPtr, + u16 *BlockPtr, u32 *BlockOffsetPtr) +{ + u32 Index; + u32 RemainderOffset; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(RegionPtr == NULL) { + return XST_FAILURE; + } + + if(BlockPtr == NULL) { + return XST_FAILURE; + } + + if(BlockOffsetPtr == NULL) { + return XST_FAILURE; + } + + /* + * Determine if the offset exceeds the device's size. + */ + if (!XFL_GEOMETRY_IS_ABSOLUTE_VALID(InstancePtr, AbsoluteOffset)) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Calculate the region. When the loop breaks, Index will index one past + * the region that the offset appears in. + */ + for (Index = 1; Index < XFL_MAX_ERASE_REGIONS; Index++) { + if (AbsoluteOffset < + InstancePtr->EraseRegion[Index].AbsoluteOffset) { + break; + } + } + + Index--; + + /* + * Calculate the remaining offset from which block and block offset + * are calculated. + */ + RemainderOffset = AbsoluteOffset - + InstancePtr->EraseRegion[Index].AbsoluteOffset; + + /* + * Calculate block & offset, assign return values and return. + */ + *RegionPtr = Index; + *BlockPtr = RemainderOffset / InstancePtr->EraseRegion[Index].Size; + *BlockOffsetPtr = RemainderOffset - + (*BlockPtr * InstancePtr->EraseRegion[Index].Size); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Sets up the VTable function pointers for the instance, based on the instance's +* Properties->CommandSet attribute. +* +* @param InstancePtr is a pointer to the Flash instance. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_NOT_SUPPORTED if no matching part is found. +* +* @note None. +* +******************************************************************************/ +static int SetVTable(XFlash * InstancePtr) +{ + + + switch (InstancePtr->CommandSet) { + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL + case XFL_CMDSET_INTEL_EXTENDED: + case XFL_CMDSET_INTEL_STANDARD: + case XFL_CMDSET_INTEL_G18: + InstancePtr->VTable.Read = XFlashIntel_Read; + InstancePtr->VTable.Write = XFlashIntel_Write; + InstancePtr->VTable.Erase = XFlashIntel_Erase; + InstancePtr->VTable.Lock = XFlashIntel_Lock; + InstancePtr->VTable.Unlock = XFlashIntel_Unlock; + InstancePtr->VTable.Initialize = XFlashIntel_Initialize; + InstancePtr->VTable.Reset = XFlashIntel_Reset; + InstancePtr->VTable.DeviceControl = + XFlashIntel_DeviceControl; + break; +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */ + +#ifdef XPAR_XFL_DEVICE_FAMILY_AMD + case XFL_CMDSET_AMD_EXTENDED: + case XFL_CMDSET_AMD_STANDARD: + InstancePtr->VTable.Read = XFlashAmd_Read; + InstancePtr->VTable.Write = XFlashAmd_Write; + InstancePtr->VTable.Erase = XFlashAmd_Erase; + InstancePtr->VTable.Lock = XFlashAmd_Lock; + InstancePtr->VTable.Unlock = XFlashAmd_Unlock; + InstancePtr->VTable.EraseChip = XFlashAmd_EraseChip; + InstancePtr->VTable.Initialize = XFlashAmd_Initialize; + InstancePtr->VTable.Reset = XFlashAmd_Reset; + InstancePtr->VTable.DeviceControl = + XFlashAmd_DeviceControl; + break; +#endif /* XPAR_XFL_DEVICE_FAMILY_AMD */ + + default: + return (XFLASH_PART_NOT_SUPPORTED); + } + + return (XST_SUCCESS); +} diff --git a/lib/sw_services/xilflash/src/xilflash_amd.c b/lib/sw_services/xilflash/src/xilflash_amd.c new file mode 100644 index 00000000..68c3de52 --- /dev/null +++ b/lib/sw_services/xilflash/src/xilflash_amd.c @@ -0,0 +1,2441 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_amd.c +* +* This file implements the AMD CFI Version of the XFlash Library. +* +* @note +* +* - Special consideration has to be given to varying data bus widths. To boost +* performance, multiple devices in parallel on the data bus are accessed +* in parallel. Therefore to reduce complexity and increase performance, +* many local primitive functions are duplicated with the only difference +* being the width of writes to the devices. +*

+* Even with the performance boosting optimizations, the overhead +* associated is rather high due to the general purpose nature of its +* design. +*

+* Flash block erasing is a time consuming operation with nearly all +* latency occurring due to the devices' themselves. It takes on the order +* of 1 second to erase each block. +*

+* Writes by comparison are much quicker so library overhead becomes an +* issue. +* The write algorithm has been optimized for bulk data programming and +* should provide relatively better performance. +* +* - This library and the underlying AMD flash memory does not allow re- +* programming while code is executing from the same memory. +* - If hardware is flakey or fails, then this library could hang a thread of +* execution. +* - This library is only tested on M29DW323DT device in 8 bit and 16 bit mode of +* operation. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.01a ksu  04/10/08 First release.
+* 1.02a ksu  06/16/09 Added Reset Bank function
+*		      Added bank(s) reset operation at the top of the read
+*		      function
+*		      Fixed memory corruption issue in 16 bit read operation
+* 2.01a ktn  03/31/10 Updated to support uniform sector WP modes.
+* 2.02a sdm  07/07/10 Updated XFlashAmd_Initialize() to NOT change the erase
+*		      region information of a top boot device, when the number
+*		      of erase regions is not more than 1.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilflash.h" + +#ifdef XPAR_XFL_DEVICE_FAMILY_AMD +#include "include/xilflash_amd.h" +#include "include/xilflash_cfi.h" + + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/* + * Define AMD specific data to be part of the instance. This structure will + * overlay the XFlash_PartData structure attribute of the base class. + */ +typedef struct XFlashVendorData_AmdTag { + /* + * The following functions are specific to the width of the data bus and + * will be assigned during initialization. + * + * SendCmd - Writes a single command to the devices. + * SendCmdSeq - Writes two commands in successive bus cycles to the + * devices. + * WriteBuffer - Programming algorithm optimized to perform bulk writes + * to devices. + * GetStatus - Retrieve and interpret the status registers of the + * devices. + * PollSR - Poll the status register of the devices until the device + * is ready. + */ + void (*SendCmd) (u32 BaseAddr, u32 Offset, u32 Cmd); + void (*SendCmdSeq) (u32 BaseAddr, u32 Offset1, u32 Offset2, u32 Cmd1, + u32 Cmd2); + void (*WriteFlash) (u32 BaseAddr, u32 Offset, u32 Cmd); + int (*WriteBuffer) (XFlash * InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); + + int (*GetStatus) (u32 BaseAddr, u32 BlockAddr); + int (*PollSR) (u32 BaseAddr, u32 BlockAddr); +} XFlashVendorData_Amd; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/***************************************************************************** +* GET_PARTDATA - Type safe way to convert the base component VendorData type +* to the family specific VendorData_Amd type. +* +* Macro signature: +* +* XFlashVendorData_Amd *GET_PARTDATA(XFlash_PartData *BaseComponent) +*****************************************************************************/ +#define GET_PARTDATA(BaseComponent) \ + ((XFlashVendorData_Amd*) ((u32)(&(BaseComponent->VendorData)))) + + +/************************** Function Prototypes ******************************/ + +static void SendCmd8(u32 BaseAddr, u32 Offset, u32 Cmd); +static void SendCmd16(u32 BaseAddr, u32 Offset, u32 Cmd); +static void SendCmd32(u32 BaseAddr, u32 Offset, u32 Cmd); + +static void SendCmdSeq8(u32 BaseAddr, u32 Offset1, u32 Offset2, u32 Cmd1, + u32 Cmd2); +static void SendCmdSeq16(u32 BaseAddr, u32 Offset1, u32 Offset2, u32 Cmd1, + u32 Cmd2); +static void SendCmdSeq32(u32 BaseAddr, u32 Offset1, u32 Offset2, u32 Cmd1, + u32 Cmd2); + +static void WriteFlash8(u32 BaseAddr, u32 Offset, u32 Cmd); +static void WriteFlash16(u32 BaseAddr, u32 Offset, u32 Cmd); +static void WriteFlash32(u32 BaseAddr, u32 Offset, u32 Cmd); + +static int WriteBuffer8(XFlash * InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); +static int WriteBuffer16(XFlash * InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); +static int WriteBuffer32(XFlash * InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); + +static int GetStatus8(u32 BaseAddr, u32 BlockAddr); +static int GetStatus16(u32 BaseAddr, u32 BlockAddr); +static int GetStatus32(u32 BaseAddr, u32 BlockAddr); + +static int PollSR8(u32 BaseAddr, u32 BlockAddr); +static int PollSR16(u32 BaseAddr, u32 BlockAddr); +static int PollSR32(u32 BaseAddr, u32 BlockAddr); + +static void GetPartID(XFlash * InstancePtr); +static u16 EnqueueEraseBlocks(XFlash * InstancePtr, u16 *Region, + u16 *Block, u16 MaxBlocks); +static int EraseResume (XFlash * InstancePtr, u32 EraseAddrOff); +static int EraseSuspend (XFlash * InstancePtr, u32 EraseAddrOff); +static void EnterExtendedBlockMode(XFlash * InstancePtr); +static void ExitExtendedBlockMode(XFlash * InstancePtr); +static int CheckBlockProtection(XFlash * InstancePtr, u32 Offset); +static void FlashPause(u32 MicroSeconds); +static int XFlashAmd_ResetBank(XFlash * InstancePtr, u32 Offset, u32 Bytes); +extern int XFlashGeometry_ToBlock(XFlashGeometry * InstancePtr, + u32 AbsoluteOffset, + u16 *Region, u16 *Block, u32 *BlockOffset); +extern int XFlashGeometry_ToAbsolute(XFlashGeometry * InstancePtr, + u16 Region, + u16 Block, + u32 BlockOffset, u32 *AbsoluteOffsetPtr); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Initializes a XFlash instance with device family specific details. The +* initialization entails: +* +* - Assign part access primitive functions depending on bus width. +* - Reset the device. +* +* @param InstancePtr is a pointer to the XFlash instance. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_PART_NOT_SUPPORTED if the command set algorithm or +* Layout is not supported by any specific flash device family +* compiled into the system. +* - XST_FAILURE if failed. +* +* @note None. +* +******************************************************************************/ +int XFlashAmd_Initialize(XFlash * InstancePtr) +{ + u8 Index; + u8 BusWidth; + u32 Layout; + u32 PartMode; + u32 ParamBlocks; + u32 ParamBlockSize; + u32 CurrentAbsoluteOffset; + u32 CurrentAbsoluteBlock; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + /* + * Grab layout and get Vendor specific part information. + */ + Layout = InstancePtr->Geometry.MemoryLayout; + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Setup alignment of the write buffer. + */ + if (InstancePtr->Properties.ProgCap.WriteBufferSize != NULL) { + InstancePtr->Properties.ProgCap.WriteBufferAlignmentMask = + InstancePtr->Properties.ProgCap.WriteBufferSize - 1; + } + + /* + * Setup layout dependent attributes. These include: + * - Part access primitive functions optimized for a specific bus + * width. + */ + switch (Layout) { + case XFL_LAYOUT_X16_X8_X1: + DevDataPtr->SendCmd = SendCmd8; + DevDataPtr->SendCmdSeq = SendCmdSeq8; + DevDataPtr->WriteFlash = WriteFlash8; + DevDataPtr->PollSR = PollSR8; + DevDataPtr->WriteBuffer = WriteBuffer8; + DevDataPtr->GetStatus = GetStatus8; + break; + + case XFL_LAYOUT_X16_X16_X1: + DevDataPtr->SendCmd = SendCmd16; + DevDataPtr->SendCmdSeq = SendCmdSeq16; + DevDataPtr->WriteFlash = WriteFlash16; + DevDataPtr->PollSR = PollSR16; + DevDataPtr->WriteBuffer = WriteBuffer16; + DevDataPtr->GetStatus = GetStatus16; + break; + + case XFL_LAYOUT_X16_X16_X2: + DevDataPtr->SendCmd = SendCmd32; + DevDataPtr->SendCmdSeq = SendCmdSeq32; + DevDataPtr->WriteFlash = WriteFlash32; + DevDataPtr->PollSR = PollSR32; + DevDataPtr->WriteBuffer = WriteBuffer32; + DevDataPtr->GetStatus = GetStatus32; + break; + + default: + return (XFLASH_PART_NOT_SUPPORTED); + } + + /* + * Get part ID and Reset the part. + */ + GetPartID(InstancePtr); + + /* + * Setup bank information as per the boot block location. + */ + + /* + * Get device operational mode. + */ + PartMode = (Layout & XFL_LAYOUT_PART_MODE_MASK); + if (PartMode == XFL_LAYOUT_PART_MODE_8) { + BusWidth = 1; + } + else if (PartMode == XFL_LAYOUT_PART_MODE_16) { + BusWidth = 2; + } + else { + return (XFLASH_PART_NOT_SUPPORTED); + } + + InstancePtr->Geometry.DeviceSize = InstancePtr->Geometry.DeviceSize / + BusWidth; + for (Index = 0; Index < InstancePtr->Geometry.NumEraseRegions; + Index++) { + InstancePtr->Geometry.EraseRegion[Index].Size = + InstancePtr->Geometry.EraseRegion[Index].Size / BusWidth; + } + /* + * If device is top boot then change erase region information. + */ + if (((InstancePtr->Geometry.BootMode == XFL_AMD_TOP_BOOT) || + (InstancePtr->Geometry.BootMode == XFL_AMD_TOP_WP_UNIFORM)) && + (InstancePtr->Geometry.NumEraseRegions > 1)) { + /* + * Move boot block region to top. + */ + ParamBlocks = InstancePtr->Geometry.EraseRegion[0].Number; + ParamBlockSize = InstancePtr->Geometry.EraseRegion[0].Size; + + InstancePtr->Geometry.EraseRegion[0].Number = + InstancePtr->Geometry.EraseRegion[1].Number; + InstancePtr->Geometry.EraseRegion[0].Size = + InstancePtr->Geometry.EraseRegion[1].Size ; + + InstancePtr->Geometry.EraseRegion[1].Number = ParamBlocks ; + InstancePtr->Geometry.EraseRegion[1].Size = ParamBlockSize; + + /* + * Calculate Erase region offset and block address. + */ + CurrentAbsoluteOffset = 0; + CurrentAbsoluteBlock = 0; + for (Index = 0; + Index < InstancePtr->Geometry.NumEraseRegions; + Index++) { + /* + * Calculate part offset. + */ + InstancePtr->Geometry.EraseRegion[Index].AbsoluteOffset + = CurrentAbsoluteOffset; + InstancePtr->Geometry.EraseRegion[Index].AbsoluteBlock + = CurrentAbsoluteBlock; + + /* + * Increment absolute counters. + */ + CurrentAbsoluteOffset += + (InstancePtr->Geometry.EraseRegion[Index].Size * + InstancePtr->Geometry.EraseRegion[Index].Number); + CurrentAbsoluteBlock += + InstancePtr->Geometry.EraseRegion[Index].Number; + } + } + else if (BusWidth != 1) { + /* + * Calculate Erase region offset and block address. + */ + CurrentAbsoluteOffset = 0; + CurrentAbsoluteBlock = 0; + for (Index = 0; + Index < InstancePtr->Geometry.NumEraseRegions; + Index++) { + /* + * Calculate part offset. + */ + InstancePtr->Geometry.EraseRegion[Index].AbsoluteOffset + = CurrentAbsoluteOffset; + InstancePtr->Geometry.EraseRegion[Index].AbsoluteBlock + = CurrentAbsoluteBlock; + + /* + * Increment absolute counters. + */ + CurrentAbsoluteOffset += + (InstancePtr->Geometry.EraseRegion[Index].Size * + InstancePtr->Geometry.EraseRegion[Index].Number); + CurrentAbsoluteBlock += + InstancePtr->Geometry.EraseRegion[Index].Number; + } + } + + + (void) XFlashAmd_Reset(InstancePtr); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* The routine reads the data from the AMD flash device and copies it into +* user buffer. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from +* which to read. +* @param Bytes is the number of bytes to copy. +* @param DestPtr is the destination address to copy data to. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the source address does not start +* within the addressable areas of the device(s). +* - XFLASH_PART_NOT_SUPPORTED if the command set algorithm or +* Layout is not supported by any specific flash device family +* compiled into the system. +* - XST_FAILURE if failed. +* +* @note None. +* +******************************************************************************/ +int XFlashAmd_Read(XFlash *InstancePtr, u32 Offset, u32 Bytes, void *DestPtr) +{ + u8 *Dest8BitPtr; + u8 *Src8BitPtr; + u16 *Dest16BitPtr; + u16 *Src16BitPtr; + u32 PartMode; + u32 Index; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + if(DestPtr == NULL) { + return (XST_FAILURE); + } + + if(Bytes == NULL) { + return (XST_FAILURE); + } + + PartMode = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_PART_MODE_MASK); + + /* + * Check to make sure start address is within the device. + */ + if (!XFL_GEOMETRY_IS_ABSOLUTE_VALID(&InstancePtr->Geometry, Offset)) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + if (XFlashAmd_ResetBank(InstancePtr, Offset, Bytes) != XST_SUCCESS) { + return (XST_FAILURE); + } + + /* + * Perform copy to the user buffer from the flash buffer. + */ + if (PartMode == XFL_LAYOUT_PART_MODE_8) { + /* + * Perform copy to the user buffer from the buffer. + */ + Src8BitPtr = (u8*) (((volatile u8*)InstancePtr->Geometry. + BaseAddress) + Offset); + Dest8BitPtr = (u8*) DestPtr; + + for (Index = 0; Index < Bytes; Index++) { + Dest8BitPtr[Index] = Src8BitPtr[Index]; + } + + } + else if (PartMode == XFL_LAYOUT_PART_MODE_16) { + /* + * Perform copy to the user buffer from the buffer. + */ + Src16BitPtr = (u16*) (((volatile u16*) InstancePtr->Geometry. + BaseAddress) + Offset); + Dest16BitPtr = (u16*) DestPtr; + + for (Index = 0; Index < (Bytes/2); Index++) { + Dest16BitPtr[Index] = Src16BitPtr[Index]; + } + } + else { + return (XFLASH_PART_NOT_SUPPORTED); + } + + return (XST_SUCCESS); +} + + +/*****************************************************************************/ +/** +* +* Programs the AMD flash device with data stored in the user buffer. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin programming. Must be aligned to the width of the +* flash's data bus. +* @param Bytes is the number of bytes to program. +* @param SrcPtr is the source address containing data to be programmed. +* Must be aligned to the width of the flash's data bus. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* - XST_FAILURE if failed. +* +* @note None. +* +******************************************************************************/ +int XFlashAmd_Write(XFlash * InstancePtr, u32 Offset, u32 Bytes, void *SrcPtr) +{ + int Status; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + if(SrcPtr == NULL) { + return (XST_FAILURE); + } + + /* + * Nothing specified to be programmed. + */ + if (Bytes == 0) { + return (XST_SUCCESS); + } + + /* + * Verify the address range is within the part. + */ + if (!XFL_GEOMETRY_IS_ABSOLUTE_VALID(&InstancePtr->Geometry, Offset) || + !XFL_GEOMETRY_IS_ABSOLUTE_VALID(&InstancePtr->Geometry, + Offset + Bytes - 1)) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Call the proper write buffer function. + */ + DevDataPtr = GET_PARTDATA(InstancePtr); + Status = DevDataPtr->WriteBuffer(InstancePtr, (void *)Offset, SrcPtr, + Bytes); + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashAmd_ResetBank(InstancePtr, Offset, Bytes); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* Erases the specified address range in the AMD Flash device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin erasure. +* @param Bytes is the number of bytes to erase. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* - XST_FAILURE if failed. +* +* @note Application has to check block protection status of all the +* which needs to be erased before calling this API. If any block +* is protected then this API will return error. +* +******************************************************************************/ +int XFlashAmd_Erase(XFlash * InstancePtr, u32 Offset, u32 Bytes) +{ + u16 StartRegion; + u16 EndRegion; + u16 StartBlock; + u16 EndBlock; + u16 BlocksLeft; + u16 BlocksQueued; + u32 Dummy; + int Status; + XFlashGeometry *GeomPtr; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + GeomPtr = &InstancePtr->Geometry; + + /* + * Handle case when zero bytes is provided. + */ + if (Bytes == 0) { + return (XST_SUCCESS); + } + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &StartRegion, + &StartBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Convert the ending address to block coordinates. This also verifies + * the ending address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset + Bytes - 1, & + EndRegion, &EndBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Erase loop. Queue up as many blocks at a time until all are erased. + */ + DevDataPtr = GET_PARTDATA(InstancePtr); + BlocksLeft = XFL_GEOMETRY_BLOCK_DIFF(GeomPtr, StartRegion, StartBlock, + EndRegion, EndBlock); + + while (BlocksLeft > 0) { + BlocksQueued = EnqueueEraseBlocks(InstancePtr, &StartRegion, + &StartBlock, BlocksLeft); + BlocksLeft -= BlocksQueued; + Status = DevDataPtr->PollSR(GeomPtr->BaseAddress, Offset); + if (Status != XFLASH_READY) { + (void) XFlashAmd_ResetBank(InstancePtr, Offset, Bytes); + return (Status); + } + } + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashAmd_ResetBank(InstancePtr, Offset, Bytes); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Locks the blocks in the specified range of the AMD flash device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin block locking. +* @param Bytes indicates the number of bytes to Lock in the Block +* starting from Offset. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* - XST_FAILURE if failed. +* +* @note This API should be called after applying VID (voltage) to the RP +* pin of flash device. This API is not tested. +* +******************************************************************************/ +int XFlashAmd_Lock(XFlash * InstancePtr, u32 Offset, u32 Bytes) +{ + u8 Mode; + u8 AddrMul; + volatile u16 StatusReg; + u16 Region; + u16 Block; + u16 NumAttempt = 0; + u32 Dummy; + u32 BaseAddress; + u32 BlockAddress; + u32 GroupAddress; + int Status; + XFlashGeometry *GeomPtr; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + + GeomPtr = &InstancePtr->Geometry; + BaseAddress = GeomPtr->BaseAddress; + + Mode = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_PART_MODE_MASK) >> 8; + + if (Mode == 2) { + AddrMul = 1; + } + else if (Mode == 1) { + AddrMul = 2; + } + else { + return (XST_FAILURE); + } + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &Region, &Block, + &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Get the physical address to write the command to and send command. + */ + (void) XFlashGeometry_ToAbsolute(GeomPtr, Region, Block, 0, + &BlockAddress); + + GroupAddress = (BlockAddress | (XFL_AMD_PROT_STATUS_OFFSET * AddrMul)); + + /* + * Set-up Phase. + */ + DevDataPtr->WriteFlash(BaseAddress, + GroupAddress, XFL_AMD_CMD_GROUP_PROTECT1); + + Status = XST_FAILURE; + do { + /* + * Protect Phase. + */ + DevDataPtr->WriteFlash(BaseAddress, + GroupAddress, XFL_AMD_CMD_GROUP_PROTECT1); + + FlashPause(100); + + /* + * Verify Phase. + */ + DevDataPtr->WriteFlash(BaseAddress, + GroupAddress, XFL_AMD_CMD_GROUP_PROTECT2); + + FlashPause(4); + + StatusReg = DevDataPtr->GetStatus(InstancePtr->Geometry. + BaseAddress, GroupAddress); + /* + * Check Protection completed. + */ + if(StatusReg == XFL_AMD_GROUP_PROTECTED) { + Status = XST_SUCCESS; + break; + } + } + while(++NumAttempt < 25); + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashAmd_ResetBank(InstancePtr, Offset, Bytes); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* Unlocks the all blocks in the AMD flash device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin block UnLocking. The first three bytes of every block +* is reserved for special purpose. The offset should be atleast +* three bytes from start of the block. +* @param Bytes indicates the number of bytes to UnLock in the Block +* starting from Offset. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed. +* +* @note This API should be called after applying VID (voltage) to the RP +* pin of flash device. This API is not tested. +* +******************************************************************************/ +int XFlashAmd_Unlock(XFlash * InstancePtr, u32 Offset, u32 Bytes) +{ + u8 Mode; + u8 AddrMul; + u8 TopBoot = 0; + u8 MakeUnprotectStep = 0; + u8 NoOfBlockInGroup; + volatile u16 StatusReg; + u16 Region = 0; + u16 NumAttempt = 0; + u16 Block = 0; + u32 BaseAddress; + u32 Index; + u32 GroupAddress; + int Status = XST_FAILURE; + XFlashGeometry *GeomPtr; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + GeomPtr = &InstancePtr->Geometry; + BaseAddress = GeomPtr->BaseAddress; + + if (InstancePtr->Geometry.BootMode == XFL_AMD_TOP_BOOT) { + TopBoot = 1; + } + + Mode = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_PART_MODE_MASK) >> 8; + + if (Mode == 2) { + AddrMul = 1; + } + else if (Mode == 1) { + AddrMul = 2; + } + else { + return (XST_FAILURE); + } + + + /* + * Protect all groups of block in the device. + */ + for (Block = 0; Block < GeomPtr->NumBlocks; Block++) { + /* + * Get the physical address. + */ + (void) XFlashGeometry_ToAbsolute(GeomPtr, Region, Block, 0, + &GroupAddress); + + if (XFlashAmd_Lock(InstancePtr, GroupAddress, NULL) != + XST_SUCCESS ) { + return XST_FAILURE; + } + + if (TopBoot) { + if ((Block == 0) || (Block >= 63)) { + NoOfBlockInGroup = 1; + } + else if ((Block == 1) || (Block == 60)) { + NoOfBlockInGroup = 3; + } + else { + NoOfBlockInGroup = 4; + } + } + else { + if ((Block <= 7) || (Block == 70)) { + NoOfBlockInGroup = 1; + } + else if ((Block == 8) || (Block == 67)) { + NoOfBlockInGroup = 3; + } + else { + NoOfBlockInGroup = 4; + } + } + + for (Index = 0; Index < NoOfBlockInGroup; Index++) { + /* + * Increment Region/Block. + */ + XFL_GEOMETRY_INCREMENT(GeomPtr, Region, Block); + Block++; + } + } + + /* + * Setup Phase. + */ + GroupAddress = (0x0000 | (AddrMul * XFL_AMD_CHIP_UNPROTECT_ADDR)); + + DevDataPtr->WriteFlash(BaseAddress, + GroupAddress, XFL_AMD_CMD_GROUP_PROTECT1); + + Block = 0; + Region = 0; + MakeUnprotectStep = 0; + while (NumAttempt < 1000) { + (void) XFlashGeometry_ToAbsolute(GeomPtr, Region, Block, 0, + &GroupAddress); + + GroupAddress = (GroupAddress | + (AddrMul * XFL_AMD_CHIP_UNPROTECT_ADDR)); + + if (MakeUnprotectStep == 0) { + /* + * Unprotect phase. + */ + DevDataPtr->WriteFlash(InstancePtr->Geometry. + BaseAddress,GroupAddress, + XFL_AMD_CMD_GROUP_PROTECT1); + + FlashPause(10000); + } + + /* + * Verify Phase. + */ + DevDataPtr->WriteFlash(InstancePtr->Geometry. + BaseAddress,GroupAddress, + XFL_AMD_CMD_GROUP_PROTECT2); + + FlashPause(4); + + StatusReg = DevDataPtr->GetStatus(InstancePtr->Geometry. + BaseAddress, GroupAddress); + + if (StatusReg == XFL_AMD_GROUP_UNPROTECTED) { + if (Block == ((GeomPtr->NumBlocks) - 1)) { + Status = XST_SUCCESS; + break; + } + else { + MakeUnprotectStep = 1; + if (TopBoot) { + if ((Block == 0) || (Block >= 63)) { + NoOfBlockInGroup = 1; + } + else if ((Block == 1) || (Block == 60)) + { + NoOfBlockInGroup = 3; + } + else { + NoOfBlockInGroup = 4; + } + } + else { + if ((Block <= 7) || (Block == 70)) { + NoOfBlockInGroup = 1; + } + else if ((Block == 8) || (Block == 67)) + { + NoOfBlockInGroup = 3; + } + else { + NoOfBlockInGroup = 4; + } + } + + for (Index = 0; Index < NoOfBlockInGroup; + Index++) { + /* + * Increment Region/Block. + */ + XFL_GEOMETRY_INCREMENT(GeomPtr, Region, + Block); + Block++; + } + } + } + else { + MakeUnprotectStep = 0; + NumAttempt++; + } + } + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashAmd_ResetBank(InstancePtr, Offset, Bytes); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* The function can be used to erase the whole flash chip. Each Block is erased +* in turn. The function only returns when all of the Blocks have been erased or +* have generated an error.. +* +* @param InstancePtr is the pointer to the XFlash instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note Application has to check block protection status of all the +* blocks before calling this API. If any block is protected then +* this API will return error. +* +******************************************************************************/ +int XFlashAmd_EraseChip(XFlash * InstancePtr) +{ + int Status = XST_SUCCESS; + XFlashGeometry *GeomPtr; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + + GeomPtr = &InstancePtr->Geometry; + + /* + * Send Chip Erase command. + */ + DevDataPtr->SendCmdSeq(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + DevDataPtr->SendCmd(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD_ERASE1); + DevDataPtr->SendCmdSeq(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->SendCmd(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD_ERASE_CHIP); + + + /* + * Wait until Program/Erase Controller starts. + */ + Status = DevDataPtr->PollSR(GeomPtr->BaseAddress, NULL); + (void) XFlashAmd_Reset(InstancePtr); + if (Status != XFLASH_READY) { + return (Status); + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function places the flash in the Read Array mode. In this mode the flash +* can be read as normal memory. All of the other functions leave the flash in +* the Read Array mode so this is not strictly necessary. It is provided for +* completeness and in case of problems. +* +* @param None. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed to reset device. +* +* @note None. +* +******************************************************************************/ + +int XFlashAmd_Reset(XFlash * InstancePtr) +{ + int Status; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + /* + * Send reset for all region/bank(s) in the device. + */ + Status = XFlashAmd_ResetBank(InstancePtr, 0, + InstancePtr->Geometry.DeviceSize); + return Status; +} + +/*****************************************************************************/ +/** +* +* This function places the flash region in the Read Array mode. In this mode the +* flash can be read as normal memory. All of the other functions leave the flash +* in the Read Array mode so this is not strictly necessary. It is provided for +* completeness and in case of problems. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the bank/region address. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if failed to reset device. +* +* @note None. +* +******************************************************************************/ + +static int XFlashAmd_ResetBank(XFlash * InstancePtr, u32 Offset, u32 Bytes) +{ + XFlashVendorData_Amd *DevDataPtr; + u16 Region, Block; + u32 Dummy, Status; + XFlashGeometry *GeomPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + /* + * Handle case when zero bytes is provided. + */ + if (Bytes == 0) { + return XST_SUCCESS; + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + GeomPtr = &InstancePtr->Geometry; + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &Region, + &Block, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + while ((InstancePtr->Geometry.EraseRegion[Region].AbsoluteOffset <= + (Offset + Bytes - 1)) && + (Region < InstancePtr->Geometry.NumEraseRegions)) { + /* + * Send the clear status register command. Use the max write + * width to notify parts of all layouts. + */ + DevDataPtr->SendCmdSeq(InstancePtr->Geometry.BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->WriteFlash(InstancePtr->Geometry.BaseAddress, + InstancePtr->Geometry.EraseRegion + [Region].AbsoluteOffset, + XFL_AMD_CMD_RESET); + /* + * Increment the region/bank. + */ + Region++; + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Performs the AMD device specific control functions. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Command is the device specific command to issue. +* @param Parameters specifies the arguments passed to the device control +* function. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_NOT_SUPPORTED if the command is not +* recognized/supported by the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlashAmd_DeviceControl(XFlash * InstancePtr, u32 Command, + DeviceCtrlParam *Parameters) +{ + u32 BlockAddr; + u32 Offset; + int Status = XST_SUCCESS; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + + switch (Command) { + case XFL_DEVCTL_GET_GEOMETRY: + Parameters->GeometryParam.GeometryPtr = + &InstancePtr->Geometry; + Status = (XST_SUCCESS); + break; + + case XFL_DEVCTL_GET_PROPERTIES: + Parameters->PropertiesParam.PropertiesPtr = + &InstancePtr->Properties; + Status = (XST_SUCCESS); + break; + + case XFL_DEVCTL_ERASE_RESUME: + BlockAddr = (*((u32*)Parameters)); + Status = EraseResume (InstancePtr, BlockAddr); + break; + + case XFL_DEVCTL_ERASE_SUSPEND: + BlockAddr = (*((u32*)Parameters)); + Status = EraseSuspend (InstancePtr, BlockAddr); + break; + + case XFL_DEVCTL_ENTER_EXT_MODE: + EnterExtendedBlockMode(InstancePtr); + Status = (XST_SUCCESS); + break; + + case XFL_DEVCTL_EXIT_EXT_MODE: + ExitExtendedBlockMode(InstancePtr); + Status = (XST_SUCCESS); + break; + + case XFL_DEVCTL_PROTECTION_STATUS: + Offset = (*((u32*)Parameters)); + Status = CheckBlockProtection(InstancePtr, Offset); + break; + + case XFL_DEVCTL_CHIP_ERASE: + Status = XFlashAmd_EraseChip(InstancePtr); + break; + + default: + Status = (XFLASH_NOT_SUPPORTED); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* Writes a command using a 8-bit bus cycle. +* +* @param BaseAddr is the base address of device. +* @param Offset is the offset into the device(s) address space on which +* command is required to be written. +* @param Cmd is the command/data to write at BaseAddress + Offset. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmd8(u32 BaseAddr, u32 Offset, u32 Cmd) +{ + Offset = ((2*Offset) + (!(Offset & 0x1))); + WRITE_FLASH_8(((volatile u8*)BaseAddr) + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command using a 16-bit bus cycle. +* +* @param BaseAddr is the base address of device. +* @param Offset is the offset into the device(s) address space on which +* command is required to be written. +* @param Cmd is the command/data to write at BaseAddress + Offset. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmd16(u32 BaseAddr, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_16(((volatile u16*)BaseAddr) + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command using a 32-bit bus cycle. +* +* @param BaseAddr is the base address of device. +* @param Offset is the offset into the device(s) address space on which +* command is required to be written. +* @param Cmd is the command/data to write at BaseAddress + Offset. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmd32(u32 BaseAddr, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_32(((volatile u32*)BaseAddr) + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command sequence using 8-bit bus cycles. +* +* @param BaseAddr is the base address of device. +* @param Offset1 is the first offset address into the device(s) address +* space on which first command (Cmd1) is required to be written. +* @param Offset2 is the second offset address into the device(s) address +* space on which second command (Cmd2) is required to be written. +* @param Cmd1 is the first command to write at BaseAddress + Offset1. +* @param Cmd2 is the second command to write at BaseAddress + Offset2. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmdSeq8(u32 BaseAddr, u32 Offset1, u32 Offset2, u32 Cmd1, + u32 Cmd2) +{ + Offset1 = ((2*Offset1) + (!(Offset1 & 0x1))); + Offset2 = ((2*Offset2) + (!(Offset2 & 0x1))); + WRITE_FLASH_8(((volatile u8*)BaseAddr) + Offset1, Cmd1); + WRITE_FLASH_8(((volatile u8*)BaseAddr) + Offset2, Cmd2); +} + +/*****************************************************************************/ +/** +* +* Writes a command sequence using 16-bit bus cycles. +* +* @param BaseAddr is the base address of device. +* @param Offset1 is the first offset address into the device(s) address +* space on which first command (Cmd1) is required to be written. +* @param Offset2 is the second offset address into the device(s) address +* space on which second command (Cmd2) is required to be written. +* @param Cmd1 is the first command to write at BaseAddress + Offset1. +* @param Cmd2 is the second command to write at BaseAddress + Offset2. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmdSeq16(u32 BaseAddr, u32 Offset1, u32 Offset2, u32 Cmd1, + u32 Cmd2) +{ + WRITE_FLASH_16(((volatile u16*)BaseAddr) + Offset1, Cmd1); + WRITE_FLASH_16(((volatile u16*)BaseAddr) + Offset2, Cmd2); +} + +/*****************************************************************************/ +/** +* +* Writes a command sequence using 32-bit bus cycles. +* +* @param BaseAddr is the base address of device. +* @param Offset1 is the first offset address into the device(s) address +* space on which first command (Cmd1) is required to be written. +* @param Offset2 is the second offset address into the device(s) address +* space on which second command (Cmd2) is required to be written. +* @param Cmd1 is the first command to write at BaseAddress + Offset1. +* @param Cmd2 is the second command to write at BaseAddress + Offset2. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmdSeq32(u32 BaseAddr, u32 Offset1, u32 Offset2, u32 Cmd1, + u32 Cmd2) +{ + WRITE_FLASH_32(((volatile u32*)BaseAddr) + Offset1, Cmd1); + WRITE_FLASH_32(((volatile u32*)BaseAddr) + Offset2, Cmd2); +} + +/*****************************************************************************/ +/** +* +* Writes a command/data using a 8-bit bus cycle. +* +* @param BaseAddr is the base address of device. +* @param Offset is the offset into the device(s) address space on which +* command is required to be written. +* @param Cmd is the command/data to write at BaseAddress + Offset. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void WriteFlash8(u32 BaseAddr, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_8(((volatile u8*)BaseAddr) + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command/data using a 16-bit bus cycle. +* +* @param BaseAddr is the base address of device. +* @param Offset is the offset into the device(s) address space on which +* command is required to be written. +* @param Cmd is the command/data to write at BaseAddress + Offset. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void WriteFlash16(u32 BaseAddr, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_16(((volatile u16*)BaseAddr) + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command/data using a 32-bit bus cycle. +* +* @param BaseAddr is the base address of device. +* @param Offset is the offset into the device(s) address space on which +* command is required to be written. +* @param Cmd is the command/data to write at BaseAddress + Offset. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void WriteFlash32(u32 BaseAddr, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_32(((volatile u32*)BaseAddr) + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* This function is used to program the memory in signal bank. It does not erase +* the flash first and will fail if the block(s) are not erased first. The +* device(s) are programmed in parallel. +* +* @param InstancePtr is the instance to work on. +* @param DestPtr is the physical destination address in flash memory +* space. +* @param SrcPtr is the source data. +* @param Bytes is the number of bytes to program. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. +* +* @note None. +* +******************************************************************************/ +static int WriteBuffer8(XFlash * InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes) +{ + u8 *SourcePtr = (u8*)SrcPtr; + u8 *DestinationPtr = (u8*)DestPtr; + u32 BaseAddress; + u32 Index = 0; + int Status = XST_SUCCESS; + XFlashVendorData_Amd *DevDataPtr; + + DevDataPtr = GET_PARTDATA(InstancePtr); + BaseAddress = InstancePtr->Geometry.BaseAddress; + + /* + * Send the Unlock Bypass command. + */ + DevDataPtr->SendCmdSeq(BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->SendCmd(BaseAddress, + XFL_AMD_CMD1_ADDR, + XFL_AMD_CMD_UNLOCK_BYPASS); + + Index = 0; + while (Bytes != NULL) { + DevDataPtr->WriteFlash(BaseAddress, + NULL, XFL_AMD_CMD_PROGRAM); + + DevDataPtr->WriteFlash(BaseAddress, + (u32)DestinationPtr, SourcePtr[Index]); + + Status = DevDataPtr->PollSR(BaseAddress, + (u32)DestinationPtr); + if (Status != XFLASH_READY) { + (void) XFlashAmd_ResetBank(InstancePtr, (u32)DestPtr, + Bytes); + return (Status); + } + DestinationPtr++; + Index++; + Bytes -= 1; + } + + /* + * Unlock Bypass Reset. + */ + DevDataPtr->WriteFlash(BaseAddress, NULL, + XFL_AMD_CMD_UNLOCK_BYPASS_RESET1); + DevDataPtr->WriteFlash(BaseAddress,NULL, + XFL_AMD_CMD_UNLOCK_BYPASS_RESET2); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function is used to program the memory in signal bank. It does not erase +* the flash first and will fail if the block(s) are not erased first. The +* device(s) are programmed in parallel. +* +* @param InstancePtr is the instance to work on. +* @param DestPtr is the physical destination address in flash memory +* space. +* @param SrcPtr is the source data. +* @param Bytes is the number of bytes to program. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. +* +* @note None. +* +******************************************************************************/ +static int WriteBuffer16(XFlash * InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes) +{ + u16 *SourcePtr = (u16*)SrcPtr; + u32 DestinationPtr = (u32)DestPtr; + u32 BaseAddress; + u32 Index = 0; + int Status = XST_SUCCESS; + XFlashVendorData_Amd *DevDataPtr; + + DevDataPtr = GET_PARTDATA(InstancePtr); + BaseAddress = InstancePtr->Geometry.BaseAddress; + + /* + * Send the Unlock Bypass command. + */ + DevDataPtr->SendCmdSeq(BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->SendCmd(BaseAddress, + XFL_AMD_CMD1_ADDR, + XFL_AMD_CMD_UNLOCK_BYPASS); + + Index = 0; + while (Bytes != NULL) { + DevDataPtr->WriteFlash(BaseAddress, + NULL, XFL_AMD_CMD_PROGRAM); + + DevDataPtr->WriteFlash(BaseAddress, + (u32)DestinationPtr, SourcePtr[Index]); + + Status = DevDataPtr->PollSR(BaseAddress, + (u32)DestinationPtr); + if (Status != XFLASH_READY) { + (void) XFlashAmd_ResetBank(InstancePtr, (u32)DestPtr, + Bytes); + return (Status); + } + DestinationPtr++; + Index++; + Bytes -= 2; + } + + /* + * Unlock Bypass Reset. + */ + DevDataPtr->WriteFlash(BaseAddress, NULL, + XFL_AMD_CMD_UNLOCK_BYPASS_RESET1); + DevDataPtr->WriteFlash(BaseAddress, NULL, + XFL_AMD_CMD_UNLOCK_BYPASS_RESET2); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function is used to program the memory in sin gal bank. It does not erase +* the flash first and will fail if the block(s) are not erased first. The +* device(s) are programmed in parallel. +* +* @param InstancePtr is the instance to work on. +* @param DestPtr is the physical destination address in flash memory +* space. +* @param SrcPtr is the source data. +* @param Bytes is the number of bytes to program. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. +* - XFLASH_NOT_SUPPORTED if the feature is not +* supported by the device(s)/library. +* +* @note None. +* +******************************************************************************/ +static int WriteBuffer32(XFlash * InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes) +{ + u32 *SourcePtr = (u32*)SrcPtr; + u32 *DestinationPtr = (u32*)DestPtr; + u32 BaseAddress; + u32 Index = 0; + int Status = XST_SUCCESS; + XFlashVendorData_Amd *DevDataPtr; + + DevDataPtr = GET_PARTDATA(InstancePtr); + BaseAddress = InstancePtr->Geometry.BaseAddress; + + /* + * Send the Unlock Bypass command . + */ + DevDataPtr->SendCmdSeq(BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->SendCmd(BaseAddress, + XFL_AMD_CMD1_ADDR, + XFL_AMD_CMD_UNLOCK_BYPASS); + Index = 0; + while (Bytes != NULL) { + DevDataPtr->WriteFlash(BaseAddress, + NULL, XFL_AMD_CMD_PROGRAM); + + DevDataPtr->WriteFlash(BaseAddress, + (u32)DestinationPtr, SourcePtr[Index]); + + Status = DevDataPtr->PollSR(BaseAddress, + (u32)DestinationPtr); + if (Status != XFLASH_READY) { + (void) XFlashAmd_ResetBank(InstancePtr, (u32)DestPtr, + Bytes); + return (Status); + } + DestinationPtr++; + Index++; + Bytes -= 4; + } + + /* + * Unlock Bypass Reset. + */ + DevDataPtr->WriteFlash(BaseAddress, NULL, + XFL_AMD_CMD_UNLOCK_BYPASS_RESET1); + DevDataPtr->WriteFlash(BaseAddress,NULL, + XFL_AMD_CMD_UNLOCK_BYPASS_RESET2); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Retrieves and interprets status register data from part arrays that occupy a +* 8-bit bus. +* +* @param BaseAddr contains base address of the part. +* @param Offset is the offset into the device(s) address space from which +* to read status information. +* +* @return +* - Status register contents. +* +* @note None. +* +******************************************************************************/ +static int GetStatus8(u32 BaseAddr, u32 Offset) +{ + return (READ_FLASH_8(((volatile u8*)BaseAddr) + Offset)); +} + + +/*****************************************************************************/ +/** +* +* Retrieves and interprets status register data from part arrays that occupy a +* 16-bit bus. +* +* @param BaseAddr contains base address of the part. +* @param Offset is the offset into the device(s) address space from which +* to read status information. +* +* @return +* - Status register contents. +* +* @note None. +* +******************************************************************************/ +static int GetStatus16(u32 BaseAddr, u32 Offset) +{ + return (READ_FLASH_16(((volatile u16*)BaseAddr) + Offset)); +} + +/*****************************************************************************/ +/** +* +* Retrieves and interprets status register data from part arrays that occupy a +* 32-bit bus. +* +* @param BaseAddr contains base address of the part. +* @param Offset is the offset into the device(s) address space from which +* to read status information. +* +* @return +* - Status register contents. +* - XFLASH_NOT_SUPPORTED if the feature is not +* supported by the device(s)/library. +* +* @note None. +* +******************************************************************************/ +static int GetStatus32(u32 BaseAddr, u32 Offset) +{ + return (READ_FLASH_32(((volatile u32*)BaseAddr) + Offset)); +} + +/*****************************************************************************/ +/** +* +* Polls the status register until the erase or program operation is completed. +* The device(s) are polled by repeatedly reading the status register. +* +* @param BaseAddr contains base address of the part. +* @param BlockAddr contains address of block on which erase or program +* operation is performed. +* +* @return - XFLASH_READY if erase operation successful is ready. +* - XFLASH_ERROR if error occurs. +* +* @note It is assumed that the status register is currently visible. +* +******************************************************************************/ +static int PollSR8(u32 BaseAddr, u32 BlockAddr) +{ + u8 StatusReg1; + u8 StatusReg2; + + while(TRUE) { + /* + * Read DQ5 and DQ6 (into word). + */ + StatusReg1 = READ_FLASH_8(((volatile u8*) BaseAddr) + + BlockAddr); + + /* + * Read DQ6 (into another word). + */ + StatusReg2 = READ_FLASH_8(((volatile u8*) BaseAddr) + + BlockAddr); + + /* + * If DQ6 did not toggle between two reads then return + * Flash_Success. + */ + if((StatusReg1 & XFL_AMD_SR_ERASE_COMPL_MASK) == + (StatusReg2 & XFL_AMD_SR_ERASE_COMPL_MASK)) { + /* + * DQ6 == NO Toggle. + */ + return (XFLASH_READY); + } + + /* + * If DQ5 is zero then operation is not yet complete. + */ + if((StatusReg2 & XFL_AMD_SR_ERASE_ERROR_MASK) != + XFL_AMD_SR_ERASE_ERROR_MASK) { + continue; + } + + /* + * Else (DQ5 == 1), read DQ6 twice. + */ + StatusReg1 = READ_FLASH_8(((volatile u8*) BaseAddr) + + BlockAddr); + StatusReg2 = READ_FLASH_8(((volatile u8*) BaseAddr) + + BlockAddr); + + /* + * If DQ6 did not toggle between two reads then return + * Flash_Success. + */ + if((StatusReg1 & XFL_AMD_SR_ERASE_COMPL_MASK) == + (StatusReg2 & XFL_AMD_SR_ERASE_COMPL_MASK)) { + /* + * DQ6 == NO Toggle. + */ + return (XFLASH_READY); + } + else { + /* + * Else return Flash_ToggleFail; DQ6 == Toggle here + * means fail. + */ + return (XFLASH_ERROR); + } + } +} + +/*****************************************************************************/ +/** +* +* Polls the status register until the erase or program operation is completed. +* The device(s) are polled by repeatedly reading the status register. +* +* @param BaseAddr contains base address of the part. +* @param BlockAddr contains address of block on which erase or program +* operation is performed. +* +* @return - XFLASH_READY if erase operation successful is ready. +* - XFLASH_ERROR if error occurs. +* +* @note It is assumed that the status register is currently visible. +* +******************************************************************************/ +static int PollSR16(u32 BaseAddr, u32 BlockAddr) +{ + u16 StatusReg1; + u16 StatusReg2; + + while(TRUE) { + /* + * Read DQ5 and DQ6 (into word). + */ + StatusReg1 = READ_FLASH_16(((volatile u16*)BaseAddr) + + BlockAddr); + + /* + * Read DQ6 (into another word). + */ + StatusReg2 = READ_FLASH_16(((volatile u16*)BaseAddr) + + BlockAddr); + + /* + * If DQ6 did not toggle between two reads then return + * Flash_Success. + */ + if((StatusReg1 & XFL_AMD_SR_ERASE_COMPL_MASK) == + (StatusReg2 & XFL_AMD_SR_ERASE_COMPL_MASK)) { + /* + * DQ6 == NO Toggle. + */ + return (XFLASH_READY); + } + + /* + * If DQ5 is zero then operation is not yet complete. + */ + if((StatusReg2 & XFL_AMD_SR_ERASE_ERROR_MASK) != + XFL_AMD_SR_ERASE_ERROR_MASK) { + continue; + } + + /* + * Else (DQ5 == 1), read DQ6 twice. + */ + StatusReg1 = READ_FLASH_16(((volatile u16*)BaseAddr) + + BlockAddr); + StatusReg2 = READ_FLASH_16(((volatile u16*)BaseAddr) + + BlockAddr); + + /* + * If DQ6 did not toggle between two reads then return + * Flash_Success. + */ + if((StatusReg1 & XFL_AMD_SR_ERASE_COMPL_MASK) == + (StatusReg2 & XFL_AMD_SR_ERASE_COMPL_MASK)) { + /* + * DQ6 == NO Toggle. + */ + return (XFLASH_READY); + } + else { + /* + * Else return Flash_ToggleFail; DQ6 == Toggle here + * means fail. + */ + return (XFLASH_ERROR); + } + } +} + +/*****************************************************************************/ +/** +* +* Polls the status register until the erase or program operation is completed. +* The device(s) are polled by repeatedly reading the status register. +* +* @param BaseAddr contains base address of the part. +* @param BlockAddr contains address of block on which erase or program +* operation is performed. +* +* @return - XFLASH_READY if erase operation successful is ready. +* - XFLASH_ERROR if error occurs. +* - XFLASH_NOT_SUPPORTED if the feature is not +* supported by the device(s)/library. +* +* @note It is assumed that the status register is currently visible. +* +******************************************************************************/ +static int PollSR32(u32 BaseAddr , u32 BlockAddr) +{ + u32 StatusReg1; + u32 StatusReg2; + + while(TRUE) { + /* + * Read DQ5 and DQ6 (into word). + */ + StatusReg1 = READ_FLASH_32(((volatile u32*)BaseAddr) + + BlockAddr); + + /* + * Read DQ6 (into another word). + */ + StatusReg2 = READ_FLASH_32(((volatile u32*)BaseAddr) + + BlockAddr); + + /* + * If DQ6 did not toggle between two reads then return + * Flash_Success. + */ + if((StatusReg1 & XFL_AMD_SR_ERASE_COMPL_MASK) == + (StatusReg2 & XFL_AMD_SR_ERASE_COMPL_MASK)) { + /* + * DQ6 == NO Toggle. + */ + return (XFLASH_READY); + } + + /* + * If DQ5 is zero then operation is not yet complete. + */ + if((StatusReg2 & XFL_AMD_SR_ERASE_ERROR_MASK) != + XFL_AMD_SR_ERASE_ERROR_MASK) { + continue; + } + + /* + * Else (DQ5 == 1), read DQ6 twice. + */ + StatusReg1 = READ_FLASH_32(((volatile u32*)BaseAddr) + + BlockAddr); + StatusReg2 = READ_FLASH_32(((volatile u32*)BaseAddr) + + BlockAddr); + + /* + * If DQ6 did not toggle between two reads then return + * Flash_Success. + */ + if((StatusReg1 & XFL_AMD_SR_ERASE_COMPL_MASK) == + (StatusReg2 & XFL_AMD_SR_ERASE_COMPL_MASK)) { + /* + * DQ6 == NO Toggle. + */ + return (XFLASH_READY); + } + else { + /* + * Else return Flash_ToggleFail; DQ6 == Toggle here + * means fail. + */ + return (XFLASH_ERROR); + } + } +} + +/*****************************************************************************/ +/** +* +* Reads and interprets part identification data. +* +* @param InstancePtr is the instance to work on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void GetPartID(XFlash * InstancePtr) +{ + void *Ptr; + u8 Mode; + u8 Interleave; + u32 CmdAddress; + XFlashVendorData_Amd *DevDataPtr; + + DevDataPtr = GET_PARTDATA(InstancePtr); + CmdAddress = InstancePtr->Geometry.BaseAddress; + Interleave = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_CFI_INTERL_MASK) >> 24; + Mode = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_PART_MODE_MASK) >> 8; + + /* + * Send Read id codes command. + */ + DevDataPtr->SendCmdSeq(CmdAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->SendCmd(CmdAddress, + XFL_AMD_CMD1_ADDR, + XFL_AMD_CMD_AUTO_SELECT); + + /* + * Retrieve Manufacturer ID located at word offset 0. + */ + XFL_CFI_POSITION_PTR(Ptr, CmdAddress, Interleave, + XFL_AMD_MANUFECTURE_ID_OFFSET); + InstancePtr->Properties.PartID.ManufacturerID = + XFlashCFI_Read8((u8*)Ptr, Interleave, Mode); + + /* + * Retrieve Device Code located at word offset 1. + */ + XFL_CFI_ADVANCE_PTR8(Ptr, Interleave); + InstancePtr->Properties.PartID.DeviceID = + XFlashCFI_Read8((u8*)Ptr, Interleave, Mode); + /* + * Place device(s) back into read-array mode. + */ + (void) XFlashAmd_Reset(InstancePtr); +} + +/*****************************************************************************/ +/** +* +* Sends commands to erase blocks. +* +* @param InstancePtr is the pointer to xflash object to work on. +* @param Region is the region which the first block appears. +* @param Block is the starting block to erase. +* @param MaxBlocks is the number of consecutive blocks to erase. +* +* @return The number of blocks enqueued to the part's erase buffer. +* Region and Block parameters are incremented the number of blocks +* queued. +* +* @note Limitation: Only support enqueuing one block at a time. +* +******************************************************************************/ +static u16 EnqueueEraseBlocks(XFlash * InstancePtr, u16 *Region, + u16 *Block, u16 MaxBlocks) +{ + u32 BlockAddress; + XFlashGeometry *GeomPtr; + XFlashVendorData_Amd *DevDataPtr; + + /* + * If for some reason the maximum number of blocks to enqueue is + * zero, then don't do anything. + */ + if (MaxBlocks == 0) { + return (0); + } + + GeomPtr = &InstancePtr->Geometry; + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Get the physical address to write the command to and send command. + */ + (void) XFlashGeometry_ToAbsolute(GeomPtr, *Region, *Block, 0, + &BlockAddress); + + /* + * Write Block Erase command. + */ + DevDataPtr->SendCmdSeq(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + DevDataPtr->SendCmd(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD_ERASE1); + DevDataPtr->SendCmdSeq(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->WriteFlash(GeomPtr->BaseAddress, BlockAddress, + XFL_AMD_CMD_ERASE_BLOCK); + + /* + * Wait until Program/Erase Controller starts. + */ + while (((DevDataPtr->GetStatus(GeomPtr->BaseAddress,BlockAddress)) & + (XFL_AMD_SR_ERASE_START_MASK)) == NULL); + + /* + * Increment Region/Block. + */ + XFL_GEOMETRY_INCREMENT(GeomPtr, *Region, *Block); + + /* + * Return the number of blocks enqueued. + */ + return (1); +} + +/*****************************************************************************/ +/** +* +* This function resumes a suspended operation on a bank of the AMD flash +* device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param EraseAddrOff holds the address inside the bank where the +* operation must be resumed. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note This API can not be used in application, because Erase API is +* blocking function in this library. If user wants to use this +* feature than Flash library Erase function should be changed such +* Erase API will be non blocking function. In case of non blocking +* Erase API, application must check status of erase operation in +* the application. +* +******************************************************************************/ +static int EraseResume(XFlash * InstancePtr, u32 EraseAddrOff) +{ + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Send the erase resume command. + */ + DevDataPtr->WriteFlash(InstancePtr->Geometry.BaseAddress, + EraseAddrOff, XFL_AMD_CMD_ERASE_RESUME); + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function suspends an erase operation on a bank of the AMD flash device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param EraseAddrOff holds the address inside the bank where the +* operation must be suspended. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if fail. +* +* @note This API can not be used in application, because Erase API is +* blocking function in this library. If user wants to use this +* feature than Flash library Erase function should be changed such +* Erase API will be non blocking function. In case of non blocking +* Erase API, application must check status of erase operation in +* the application. +* +******************************************************************************/ +static int EraseSuspend(XFlash * InstancePtr, u32 EraseAddrOff) +{ + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Send the erase suspend command. + */ + DevDataPtr->WriteFlash(InstancePtr->Geometry.BaseAddress, + EraseAddrOff, XFL_AMD_CMD_ERASE_SUSPEND); + + /* + * Wait until Toggle Stops. + */ + (void) DevDataPtr->PollSR(InstancePtr->Geometry.BaseAddress, + EraseAddrOff); + + /* + * Return to Read mode. + */ + (void) XFlashAmd_Reset(InstancePtr); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function will make the device to enter into Extended Block Mode, where +* the Extended Block can be read and written, using the Boot block addresses. +* +* @param InstancePtr is the pointer to the XFlash instance. +* +* @return +* None. +* +* @note None. +* +******************************************************************************/ +static void EnterExtendedBlockMode(XFlash * InstancePtr) +{ + XFlashVendorData_Amd *DevDataPtr; + + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Issue Enter Extended Block Command. + */ + DevDataPtr->SendCmdSeq(InstancePtr->Geometry.BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->SendCmd(InstancePtr->Geometry.BaseAddress, + XFL_AMD_CMD1_ADDR, + XFL_AMD_CMD_ENTER_EXT_MODE); +} + +/*****************************************************************************/ +/** +* +* This command returns the device to Read mode from Extended Block Mode. +* +* @param InstancePtr is the pointer to the XFlash instance. +* +* @return +* None. +* +* @note None. +* +******************************************************************************/ +static void ExitExtendedBlockMode(XFlash * InstancePtr) +{ + XFlashVendorData_Amd *DevDataPtr; + + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Issue Exit Extended Block Command. + */ + DevDataPtr->SendCmdSeq(InstancePtr->Geometry.BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->SendCmd(InstancePtr->Geometry.BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD_EXIT_EXT_MODE); + + DevDataPtr->WriteFlash(InstancePtr->Geometry.BaseAddress, + NULL, NULL); +} + +/*****************************************************************************/ +/** +* +* This function reads the protection status of a block group. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from where +* to read protection status. +* +* @return +* - XST_SUCCESS if block is not protected. +* - XFLASH_BLOCK_PROTECTED if block is protected. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* - XST_FAILURE if block protection is unclear. +* +* @note None. +* +******************************************************************************/ +static int CheckBlockProtection(XFlash * InstancePtr, u32 Offset) +{ + u8 Mode; + u8 AddrMul; + u16 Region; + u16 Block; + u32 Dummy; + u32 BlockAddress; + u32 CmdAddress; + u32 ProtStatus; + int Status; + XFlashGeometry *GeomPtr; + XFlashVendorData_Amd *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return (XST_FAILURE); + } + + GeomPtr = &InstancePtr->Geometry; + + DevDataPtr = GET_PARTDATA(InstancePtr); + + Mode = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_PART_MODE_MASK) >> 8; + if (Mode == 2) { + AddrMul = 1; + } + else if (Mode == 1) { + AddrMul = 2; + } + else { + return (XST_FAILURE); + } + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &Region, &Block, + &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Get the physical address to write the command to and send command. + */ + (void) XFlashGeometry_ToAbsolute(GeomPtr, Region, Block, 0, + &BlockAddress); + + CmdAddress = BlockAddress | ((XFL_AMD_CMD1_ADDR * AddrMul) + !( + XFL_AMD_CMD1_ADDR & 0x1)); + + /* + * Send the command. + */ + DevDataPtr->SendCmdSeq(GeomPtr->BaseAddress, + XFL_AMD_CMD1_ADDR, XFL_AMD_CMD2_ADDR, + XFL_AMD_CMD1_DATA, XFL_AMD_CMD2_DATA); + + DevDataPtr->WriteFlash(InstancePtr->Geometry.BaseAddress, + CmdAddress, XFL_AMD_CMD_AUTO_SELECT); + + /* + * Retrieve Protection Status located at word offset 2. + */ + CmdAddress = BlockAddress + (XFL_AMD_PROT_STATUS_OFFSET * AddrMul); + + ProtStatus = DevDataPtr->GetStatus(GeomPtr->BaseAddress, CmdAddress); + if(ProtStatus == XFL_AMD_GROUP_UNPROTECTED) { + Status = XST_SUCCESS; + } + else if(ProtStatus == XFL_AMD_GROUP_PROTECTED) { + Status = XFLASH_BLOCK_PROTECTED; + } + else { + Status = XST_FAILURE; + } + + /* + * Return to Read mode. + */ + (void) XFlashAmd_Reset(InstancePtr); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This routine returns after MicroSeconds have elapsed. It is used in several +* parts of the code to generate a pause required for correct operation of the +* flash part. +* +* @param MicroSeconds is the length of the pause in microseconds. +* +* @return +* None +* +* @note None. +* +******************************************************************************/ +static void FlashPause(u32 MicroSeconds) +{ + static u32 Counter; + + /* + * Compute the count size. + */ + Counter = MicroSeconds * XFL_COUNT_FOR_A_MICROSECOND ; + + /* + * Count to the required size. + */ + while(Counter > 0) { + /* + * Count down. + */ + Counter--; + } +} + +#endif /* XPAR_XFL_DEVICE_FAMILY_AMD */ diff --git a/lib/sw_services/xilflash/src/xilflash_cfi.c b/lib/sw_services/xilflash/src/xilflash_cfi.c new file mode 100644 index 00000000..8cd4ee39 --- /dev/null +++ b/lib/sw_services/xilflash/src/xilflash_cfi.c @@ -0,0 +1,870 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_cfi.c +* +* The file implements the functions for retrieval and translation of CFI data +* from a compliant flash device. CFI contains data that defines part geometry, +* write/erase timing, and programming data. +* +* Data is retrieved using macros defined in this xflash_cfi.h file. The +* macros simplify data extraction because they have been written to take into +* account the layout of parts on the data bus. To the library, CFI data appears +* as if it were always being read from a single 8-bit part (XFL_LAYOUT_X8_X8_X1) +* Otherwise, the retrieval code would have to contend with all the formats +* illustrated below. The illustration shows how the first three bytes of the CFI +* query data "QRY" appear in flash memory space for various part layouts. +*
+*
+*			Byte Offset (Big-Endian)
+*			0123456789ABCDEF
+*			----------------
+*			XFL_LAYOUT_X16_X16_X1	Q R Y
+*			XFL_LAYOUT_X16_X16_X2	Q Q R R Y Y
+* 
+* +* Where the holes between Q, R, and Y are NULL (all bits 0) +* +* @note +* +* This code 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 +* management must be satisfied by the layer above this library. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  10/25/07 First release
+* 1.00a mta  10/25/07 Updated to flash library
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 1.02a ksu  08/06/09 Added code to read the platform flash bank information
+* 2.00a ktn  12/04/09 Updated to use the HAL processor APIs/macros
+* 2.02a sdm  06/30/10 Updated to support AXI EMC with Little Endian Processor
+* 3.00a sdm  03/03/11 Removed static parameters in mld and updated code to
+*		      determine these parameters from the CFI data.
+* 3.01a srt  03/02/12 Added support for Micron G18 Flash device to fix
+*		      CRs 648372, 648282.
+*		      Added DATA_SYNC to fix the CR 644750.
+* 3.02a srt  05/30/12 Changed Implementation for Micron G18 Flash, which
+*		      fixes the CR 662317.
+*		      CR 662317 Description - Xilinx Platform Flash on ML605
+*		      fails to work.
+* 3.04a srt  02/18/13 Fixed CR 700553.
+* 
+* +* +****************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "include/xilflash.h" +#include "include/xilflash_cfi.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Retrieves the standard CFI data from the part(s), interpret the data, and +* update the provided geometry and properties structures. +* +* Extended CFI data is part specific and ignored here. This data must be read +* by the specific flash device family library. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param BusWidth is the total width of the flash memory, in bytes. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_CFI_QUERY_ERROR if an error occurred interpreting +* the data. +* - XFLASH_PART_NOT_SUPPORTED if invalid Layout parameter. +* +* @note None. +* +******************************************************************************/ +int XFlashCFI_ReadCommon(XFlash *InstancePtr, u8 BusWidth) +{ + void *DataPtr; + u32 BaseAddress; + int Status = XST_SUCCESS; + u8 Data8; + u8 Mode; + u8 DataQRY[3]; + u16 Data16; + u16 ExtendedQueryTblOffset; + u32 SizeMultiplier; + u32 CurrentAbsoluteOffset; + u16 CurrentAbsoluteBlock; + u32 Index; + u32 Interleave; + u32 CfiQryAddr; + u32 Layout; + u32 Data32; + Xuint64 Data64; + u16 NumBanks, Bank; + u16 NumEraseRegions; + u8 TypesEraseBlock; + u16 NumBlockInBank; + u32 SizeBlockInBank; + XFlashGeometry *GeomPtr; + + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + BaseAddress = InstancePtr->Geometry.BaseAddress; + CfiQryAddr = 0x10; + + switch (BusWidth) { + case 1: + /* Check for one 16 bit flash in x8 mode */ + WRITE_FLASH_8(BaseAddress, 0xFF); + WRITE_FLASH_8(BaseAddress + 0xAA, 0x98); + DATA_SYNC; + Data8 = READ_FLASH_8(BaseAddress + (CfiQryAddr << 1)); + if (Data8 == 0x51) { + Layout = XFL_LAYOUT_X16_X8_X1; + } else { + Layout = XFLASH_PART_NOT_SUPPORTED; + } + + break; + + case 2: + /* Check for one 16 bit flash in x16 mode */ + CfiQryAddr <<= 1; + WRITE_FLASH_16(BaseAddress, 0xFF); + WRITE_FLASH_16(BaseAddress + 0xAA, 0x98); + DATA_SYNC; + Data16 = READ_FLASH_16(BaseAddress + CfiQryAddr); + if (Data16 == 0x51) { + Layout = XFL_LAYOUT_X16_X16_X1; + } else { + Layout = XFLASH_PART_NOT_SUPPORTED; + } + + break; + + case 4: + /* Check for two 16 bit flash devices in x32 mode */ + CfiQryAddr <<= 2; + WRITE_FLASH_32(BaseAddress, 0x00FF00FF); + WRITE_FLASH_32(BaseAddress + 0xAA, 0x00980098); + DATA_SYNC; + Data32 = READ_FLASH_32(BaseAddress + CfiQryAddr); + if (Data32 == 0x00510051) { + Layout = XFL_LAYOUT_X16_X16_X2; + } else { + Layout = XFLASH_PART_NOT_SUPPORTED; + } + + break; + + case 8: + /* Check for four 16 bit flash devices in x64 mode */ + CfiQryAddr <<= 3; + WRITE_FLASH_64x2(BaseAddress + 0xAA, + 0x00FF00FF, 0x00FF00FF); + WRITE_FLASH_64x2(BaseAddress + 0xAA, + 0x00980098, 0x00980098); + DATA_SYNC; + READ_FLASH_64(BaseAddress + CfiQryAddr, Data64); + if ((XUINT64_MSW(Data64) == 0x00510051) && + (XUINT64_LSW(Data64) == 0x00510051)) { + Layout = XFL_LAYOUT_X16_X16_X4; + } else { + Layout = XFLASH_PART_NOT_SUPPORTED; + } + + break; + + default: + Layout = XFLASH_PART_NOT_SUPPORTED; + } + + if (Layout == XFLASH_PART_NOT_SUPPORTED) { + return (XFLASH_PART_NOT_SUPPORTED); + } + + InstancePtr->Geometry.MemoryLayout = Layout; + + /* + * To stay consistent when retrieving the CFI data for all part layouts + * we use the XFL_CFI_READ macros supplying the correct interleave based + * on the layout. + * + * The size of a block for an instance is the block size reported + * by the device multiplied by the number of devices (SizeMultiplier). + */ + Interleave = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_CFI_INTERL_MASK) >> 24; + SizeMultiplier = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_NUM_PARTS_MASK); + Mode = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_PART_MODE_MASK) >> 8; + + /* + * Begin reading the data. Each datum is documented in comments with + * its offset range. + */ + + /* + * 10h-12h : Contains the "QRY" string. Must be present. + */ + XFL_CFI_POSITION_PTR(DataPtr, BaseAddress, Interleave, 0x10); + + DataQRY[0] = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + DataQRY[1] = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + DataQRY[2] = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + + if ((DataQRY[0] != 'Q') || (DataQRY[1] != 'R') || (DataQRY[2] != 'Y')) { + Status = XFLASH_CFI_QUERY_ERROR; + } + else { + /* + * 13h-14h : Primary vender command set. + */ + XFL_CFI_POSITION_PTR(DataPtr, BaseAddress, Interleave, 0x13); + InstancePtr->Properties.PartID.CommandSet = + XFlashCFI_Read16((u8*)DataPtr, Interleave, Mode); + InstancePtr->CommandSet = + InstancePtr->Properties.PartID.CommandSet; + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL + /* Support for Micron G18. This flash is partially compatible + with Intel CFI command set and it has a different geometry + from the other Intel Flash Devices */ + if (InstancePtr->CommandSet == XFL_CMDSET_INTEL_G18) { + InstancePtr->Command.WriteBufferCommand = + XFL_INTEL_G18_CMD_WRITE_BUFFER; + InstancePtr->Command.ProgramCommand = + XFL_INTEL_G18_CMD_PROGRAM; + } + else { + InstancePtr->Command.WriteBufferCommand = + XFL_INTEL_CMD_WRITE_BUFFER; + InstancePtr->Command.ProgramCommand = + XFL_INTEL_CMD_PROGRAM; + } +#endif + + /* + * 15h-16h : Address for Primary Algorithm extended Query table. + */ + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + ExtendedQueryTblOffset = + XFlashCFI_Read16((u8*)DataPtr, Interleave, Mode); + + /* + * 17h-1Ah : Vendor data to be interpreted by part (ignored + * here). + * 1Bh-1Eh : Voltage requirements (ignored by this library). + * + * Interpret the timing requirements starting here. + * 1Fh : Typical timeout for single byte/word program cycle + * (2^N Us). + */ + XFL_CFI_POSITION_PTR(DataPtr, BaseAddress, Interleave, 0x1F); + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + if (Data8 != 0) { + InstancePtr->Properties.TimeTypical.WriteSingle_Us = + 1 << Data8; + } + + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 20h:Typical timeout for max buffer program cycle (2^N Us) + * = 0 if not supported. + */ + + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + if (Data8 != 0) { + InstancePtr->Properties.TimeTypical.WriteBuffer_Us = + 1 << Data8; + } + + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 21h : Typical timeout for single block erase (2^N Ms). + */ + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + if (Data8 != 0) { + InstancePtr->Properties.TimeTypical.EraseBlock_Ms = + 1 << Data8; + } + + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 22h : Typical timeout for full chip erase (2^N Ms) + * = 0 if not supported. + */ + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + if (Data8 != 0) { + InstancePtr->Properties.TimeTypical.EraseChip_Ms = + 1 << Data8; + } + + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 23h : Maximum timeout for single byte/word program cycle + * (2^N * typical time). + */ + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + InstancePtr->Properties.TimeMax.WriteSingle_Us = + InstancePtr->Properties.TimeTypical.WriteSingle_Us * + (1 << Data8); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 24h : Maximum timeout for max buffer program cycle + * (2^N * typical time) + * = 0 if not supported. + */ + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + InstancePtr->Properties.TimeMax.WriteBuffer_Us = + InstancePtr->Properties.TimeTypical.WriteBuffer_Us * + (1 << Data8); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 25h : Maximum timeout for single block erase + * (2^N * typical time). + */ + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + InstancePtr->Properties.TimeMax.EraseBlock_Ms = + InstancePtr->Properties.TimeTypical.EraseBlock_Ms * + (1 << Data8); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 26h : Maximum timeout for full chip erase + * (2^N * typical time) + * = 0 if not supported. + */ + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + InstancePtr->Properties.TimeMax.EraseChip_Ms = + InstancePtr->Properties.TimeTypical.EraseChip_Ms * + (1 << Data8); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 27h : Device size in bytes + * = 2^N bytes * (Number of parts). + */ + Data8 = XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + InstancePtr->Geometry.DeviceSize = (1 << Data8) * + SizeMultiplier; + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 28h-29h : Device interface description (ignored). + */ + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + + /* + * 2Ah-2Bh : Maximum number of bytes in write buffer + * = 2^N bytes * (Number of parts). + */ + Data16 = XFlashCFI_Read16((u8*)DataPtr, Interleave, Mode); + if (Data16 != 0) { + InstancePtr->Properties.ProgCap.WriteBufferSize = + (1 << Data16) * SizeMultiplier; + } + + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + + /* + * 2Ch : Number of erase regions. + * Make sure there are not too many to contain in the instance. + * This will ensure the for loop below doesn't go out of bounds + * on the Geometry.EraseRegion array. + */ + InstancePtr->Geometry.NumEraseRegions = XFlashCFI_Read8( + (u8*)DataPtr, + Interleave, + Mode); + if ((InstancePtr->CommandSet == XFL_CMDSET_AMD_STANDARD) || + (InstancePtr->CommandSet == XFL_CMDSET_AMD_EXTENDED)) { + if (InstancePtr->Geometry.NumEraseRegions > + XFL_AMD_MAX_ERASE_REGIONS) { + return (XFLASH_TOO_MANY_REGIONS); + } + } else { + if (InstancePtr->Geometry.NumEraseRegions > + XFL_INTEL_MAX_ERASE_REGIONS) { + return (XFLASH_TOO_MANY_REGIONS); + } + } + + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * 2Dh-30h : Erase region #1 definition + * 31h-34h : Erase region #2 definition + * 35h-39h : Erase region #3 definition, etc. + */ + CurrentAbsoluteOffset = 0; + CurrentAbsoluteBlock = 0; + InstancePtr->Geometry.NumBlocks = 0; + for (Index = 0; Index < InstancePtr->Geometry.NumEraseRegions; + Index++) { + + /* + * Offset 0-1 : Number of blocks in the region + * = N + 1. + */ + Data16 = XFlashCFI_Read16((u8*)DataPtr, Interleave, + Mode); + InstancePtr->Geometry.EraseRegion[Index].Number = Data16 + + 1; + InstancePtr->Geometry.NumBlocks += + InstancePtr->Geometry.EraseRegion[Index].Number; + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + + /* + * Offset 2-3 : Size of erase blocks in the region + * = N * 256 * (Number of parts). + */ + Data16 = XFlashCFI_Read16((u8*)DataPtr, Interleave, + Mode); + InstancePtr->Geometry.EraseRegion[Index].Size = + Data16 * 256 * SizeMultiplier; + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + + /* + * Calculate the part offset where this region begins. + */ + InstancePtr->Geometry.EraseRegion[Index].AbsoluteOffset + = CurrentAbsoluteOffset; + InstancePtr->Geometry.EraseRegion[Index].AbsoluteBlock = + CurrentAbsoluteBlock; + + /* + * Increment absolute counters. + */ + CurrentAbsoluteOffset += + (InstancePtr->Geometry.EraseRegion[Index].Size * + InstancePtr->Geometry.EraseRegion[Index].Number); + CurrentAbsoluteBlock += + InstancePtr->Geometry.EraseRegion[Index].Number; + } + + /* + * Set the absolute offsets for NumEraseRegions+1. This is not a + * real region, but marks one unit past the part's addressable + * region. For example, if the device(s) are a total of 1000 + * bytes in size with a total of 10 blocks then 1000 and 10 are + * written to the Absolute parameters. The Size & Number are + * left as zero. + */ + InstancePtr->Geometry.EraseRegion[Index].AbsoluteOffset = + CurrentAbsoluteOffset; + InstancePtr->Geometry.EraseRegion[Index].AbsoluteBlock = + CurrentAbsoluteBlock; + + /* + * This ends the query. The following summarizes what attributes + * of the InstancePtr were initialized: + * + * Properties.PartID + * - CommandSet defined. + * - ManufacturerID is defined by the part's Initialize + * function. + * - DeviceID is defined by the part's Initialize function. + * + * Properties.TimeTypical + * Completely defined. + * + * Properties.TimeMax + * Completely defined. + * + * Properties.ProgCap + * - WriteBufferAlignment must be defined by the device. + * It defaults to 0 here. + * - EraseQueueSize must be defined by the device. It + * defaults to 1 here. + * + * Geometry + * Completely defined. + * + */ + InstancePtr->Properties.ProgCap.EraseQueueSize = 1; + + /* + * Some of AMD flash have different geometry based on + * type of boot mode. Read boot mode to identify + * location of boot block and parameter blocks. + */ + if (InstancePtr->CommandSet == 0x02) { + /* + * Extended Query Table Offset + 0x0F: Boot mode. + */ + XFL_CFI_POSITION_PTR(DataPtr, BaseAddress, Interleave, + (ExtendedQueryTblOffset + 0x0F)); + InstancePtr->Geometry.BootMode = + XFlashCFI_Read8((u8*)DataPtr, Interleave, Mode); + } + + /* + * The platform flash (Intel) have multiple banks in same erase + * region. Read number of identical banks in each erase region, + * number of erase blocks and size of blocks in each bank. For + * platfrom flash, library treats each bank as seperate region. + */ + if (((InstancePtr->CommandSet == XFL_CMDSET_INTEL_STANDARD) || + (InstancePtr->CommandSet == XFL_CMDSET_INTEL_EXTENDED)) && + (InstancePtr->IsPlatformFlash == 1)) { + + Index = 0; + NumEraseRegions = InstancePtr->Geometry.NumEraseRegions; + InstancePtr->Geometry.NumEraseRegions = 0; + CurrentAbsoluteOffset = 0; + CurrentAbsoluteBlock = 0; + Bank = 0; + GeomPtr = &InstancePtr->Geometry; + while (Index < NumEraseRegions) { + /* + * Extended Query Table Offset + 0x24/0x32: + * Number of banks in region. + */ + XFL_CFI_POSITION_PTR(DataPtr, BaseAddress, + Interleave, (ExtendedQueryTblOffset + + 0x24 + (Index * 0x0E))); + NumBanks = XFlashCFI_Read16((u8*)DataPtr, + Interleave, Mode); + /* + * Ignore the information about multiple + * operation in bank and region as it is not + * supported by the library + */ + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * Extended Query Table Offset + 0x29/0x37: + * Types of erase block in the bank + */ + TypesEraseBlock = + XFlashCFI_Read8((u8*)DataPtr, + Interleave, Mode); + + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + while (TypesEraseBlock--) { + /* + * Number of erase block in bank + */ + NumBlockInBank = + XFlashCFI_Read16((u8*)DataPtr, + Interleave, Mode); + NumBlockInBank += 1; + XFL_CFI_ADVANCE_PTR16(DataPtr, + Interleave); + /* + * Size of each erase block in bank + */ + SizeBlockInBank = + XFlashCFI_Read16((u8*)DataPtr, + Interleave, Mode); + SizeBlockInBank *= 256; + /* + * Update flash instance structure + */ + GeomPtr->NumEraseRegions += NumBanks; + while (Bank < GeomPtr->NumEraseRegions){ + GeomPtr->EraseRegion[Bank]. + Number = NumBlockInBank; + GeomPtr->EraseRegion[Bank].Size + = SizeBlockInBank; + GeomPtr->EraseRegion[Bank]. + AbsoluteOffset = + CurrentAbsoluteOffset; + GeomPtr->EraseRegion[Bank]. + AbsoluteBlock = + CurrentAbsoluteBlock; + + CurrentAbsoluteOffset += + (GeomPtr->EraseRegion + [Bank].Size * + GeomPtr->EraseRegion + [Bank].Number); + CurrentAbsoluteBlock += + GeomPtr->EraseRegion + [Bank].Number; + Bank++; + } + XFL_CFI_ADVANCE_PTR16(DataPtr, + Interleave); + XFL_CFI_ADVANCE_PTR16(DataPtr, + Interleave); + XFL_CFI_ADVANCE_PTR16(DataPtr, + Interleave); + } + Index++; + } + GeomPtr->EraseRegion[Bank].AbsoluteOffset = + CurrentAbsoluteOffset; + GeomPtr->EraseRegion[Bank].AbsoluteBlock = + CurrentAbsoluteBlock; + } + + /* + * The Micron G18 flash (Intel) have multiple banks in same erase + * region. Read number of identical banks in each erase region, + * number of erase blocks and size of blocks in each bank. For + * Micron G18 flash, library treats each bank as seperate region. + */ + if (InstancePtr->CommandSet == XFL_CMDSET_INTEL_G18) { + Index = 0; + NumEraseRegions = InstancePtr->Geometry.NumEraseRegions; + InstancePtr->Geometry.NumEraseRegions = 0; + CurrentAbsoluteOffset = 0; + CurrentAbsoluteBlock = 0; + Bank = 0; + GeomPtr = &InstancePtr->Geometry; + + while (Index < NumEraseRegions) { + /* + * Extended Query Table Offset + 0x22: + * Number of banks in region. + */ + XFL_CFI_POSITION_PTR(DataPtr, BaseAddress, + Interleave, (ExtendedQueryTblOffset + + 0x25)); + NumBanks = XFlashCFI_Read8((u8*)DataPtr, + Interleave, Mode); + + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + XFL_CFI_ADVANCE_PTR16(DataPtr, Interleave); + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + + /* + * Extended Query Table Offset + 0x2A: + * Types of erase block in the bank + */ + TypesEraseBlock = + XFlashCFI_Read8((u8*)DataPtr, + Interleave, Mode); + + XFL_CFI_ADVANCE_PTR8(DataPtr, Interleave); + while (TypesEraseBlock--) { + /* + * Number of erase block in bank + */ + NumBlockInBank = + XFlashCFI_Read16((u8*)DataPtr, + Interleave, Mode); + NumBlockInBank += 1; + XFL_CFI_ADVANCE_PTR16(DataPtr, + Interleave); + /* + * Size of each erase block in bank + */ + SizeBlockInBank = + XFlashCFI_Read16((u8*)DataPtr, + Interleave, Mode); + SizeBlockInBank *= 256; + + /* + * Update flash instance structure + */ + GeomPtr->NumEraseRegions += NumBanks; + while (Bank < GeomPtr->NumEraseRegions){ + GeomPtr->EraseRegion[Bank]. + Number = NumBlockInBank; + GeomPtr->EraseRegion[Bank].Size + = SizeBlockInBank; + GeomPtr->EraseRegion[Bank]. + AbsoluteOffset = + CurrentAbsoluteOffset; + GeomPtr->EraseRegion[Bank]. + AbsoluteBlock = + CurrentAbsoluteBlock; + + CurrentAbsoluteOffset += + (GeomPtr->EraseRegion + [Bank].Size * + GeomPtr->EraseRegion + [Bank].Number); + CurrentAbsoluteBlock += + GeomPtr->EraseRegion + [Bank].Number; + Bank++; + } + } + Index++; + } + GeomPtr->EraseRegion[Bank].AbsoluteOffset = + CurrentAbsoluteOffset; + GeomPtr->EraseRegion[Bank].AbsoluteBlock = + CurrentAbsoluteBlock; + } + } + + switch (InstancePtr->Geometry.MemoryLayout) { + case XFL_LAYOUT_X16_X8_X1: + WRITE_FLASH_8(BaseAddress + 0xAA, 0xFF); + break; + + case XFL_LAYOUT_X16_X16_X1: + WRITE_FLASH_16(BaseAddress + 0xAA, 0xFF); + break; + + case XFL_LAYOUT_X16_X16_X2: + WRITE_FLASH_32(BaseAddress + 0xAA, 0x00FF00FF); + break; + + case XFL_LAYOUT_X16_X16_X4: + WRITE_FLASH_64x2(BaseAddress + 0xAA, + 0x00FF00FF, 0x00FF00FF); + break; + } + + return (Status); +} + +#ifdef XPAR_AXI_EMC +/*****************************************************************************/ +/** +* +* Reads 8-bits of data from the CFI data location into a local variable. +* +* @param Ptr is the pointer to read. Can be a pointer to any type. +* @param Interleave is the byte interleaving (based on part layout). +* @param Mode is the mode of operation (based on part layout). +* +* @return The byte at Ptr adjusted for the interleave factor. +* +*****************************************************************************/ +int XFlashCFI_Read8(u8 *Ptr, u8 Interleave, u8 Mode) +{ + return (READ_FLASH_8((u32)Ptr)); +} + +/*****************************************************************************/ +/** +* +* Reads 16-bits of data from the CFI data location into a local variable. +* +* @param Ptr is the pointer to read. Can be a pointer to any type. +* @param Interleave is the byte interleaving (based on part layout). +* @param Mode is the mode of operation (based on part layout). +* +* @return The 16-bit value at Ptr adjusted for the interleave factor. +* +*****************************************************************************/ +int XFlashCFI_Read16(u8 *Ptr, u8 Interleave, u8 Mode) +{ + int Data = 0; + + (Data) = (u8)READ_FLASH_8((u8*)(Ptr) + Interleave); + (Data) <<= 8; + (Data) |= (u8)READ_FLASH_8((u8*)(Ptr)); + + return Data; +} + +#else /* XPAR_XPS_MCH_EMC */ +/*****************************************************************************/ +/** +* +* Reads 8-bits of data from the CFI data location into a local variable. +* +* @param Ptr is the pointer to read. Can be a pointer to any type. +* @param Interleave is the byte interleaving (based on part layout). +* @param Mode is the mode of operation (based on part layout). +* +* @return The byte at Ptr adjusted for the interleave factor. +* +*****************************************************************************/ +int XFlashCFI_Read8(u8 *Ptr, u8 Interleave, u8 Mode) +{ + if (Mode == (u8)1) { + Interleave = 1; + } + + return (READ_FLASH_8((u32)Ptr + Interleave - 1)); +} + +/*****************************************************************************/ +/** +* +* Reads 16-bits of data from the CFI data location into a local variable. +* +* @param Ptr is the pointer to read. Can be a pointer to any type. +* @param Interleave is the byte interleaving (based on part layout). +* @param Mode is the mode of operation (based on part layout). +* +* @return The 16-bit value at Ptr adjusted for the interleave factor. +* +*****************************************************************************/ +int XFlashCFI_Read16(u8 *Ptr, u8 Interleave, u8 Mode) +{ + int Data = 0; + + if (Mode == (u8)1) { + (Data) = (u8)READ_FLASH_8((u8*)(Ptr) + Interleave); + (Data) <<= 8; + (Data) |= (u8)READ_FLASH_8((u8*)(Ptr)); + } + else if (Mode == (u8)2) { + (Data) = (u16)READ_FLASH_8((u8*)(Ptr) + ((Interleave) * 2) - 1); + (Data) <<= 8; + (Data) |= (u16)READ_FLASH_8((u8*)(Ptr) + (Interleave) - 1); + } + + return Data; +} +#endif /* XPAR_AXI_EMC */ diff --git a/lib/sw_services/xilflash/src/xilflash_intel.c b/lib/sw_services/xilflash/src/xilflash_intel.c new file mode 100644 index 00000000..1e6f6248 --- /dev/null +++ b/lib/sw_services/xilflash/src/xilflash_intel.c @@ -0,0 +1,2973 @@ +/****************************************************************************** +* +* Copyright (C) 2007 - 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 xilflash_intel.c +* +* This file implements the Intel CFI Version of the XFlash Library. +* +* @note +* +* - Special consideration has to be given to varying data bus widths. To boost +* performance, multiple devices in parallel on the data bus are accessed +* in parallel. Therefore to reduce complexity and increase performance, +* many local primitive functions are duplicated with the only difference +* being the width of writes to the devices. +*

+* Even with the performance boosting optimizations, the overhead +* associated is rather high due to the general purpose nature of its +* design. +*

+* Flash block erasing is a time consuming operation with nearly all +* latency occurring due to the devices' themselves. It takes on the order +* of 1 second to erase each block. +*

+* Writes by comparison are much quicker so library overhead becomes an +* issue. +* The write algorithm has been optimized for bulk data programming and +* should provide relatively better performance. +* - The code/comments refers to WSM frequently. This stands for Write State +* Machine. WSM is the internal programming engine of the devices. +* - This library and the underlying Intel flash memory does not allow re- +* programming while code is executing from the same memory. +* - If hardware is flakey or fails, then this library could hang a thread of +* execution. +* +*
+*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a rmm  10/25/07 First release
+* 1.00a mta  10/25/07 Updated to flash library
+* 1.01a ksu  04/10/08 Added support for AMD CFI Interface
+* 1.02a ksu  06/16/09 Added support for multiple banks in Intel flash
+*                     Added Reset Bank function
+*                     Added support for 0xF0 reset command
+*                     Added support for Xilinx Platform Flash XL.
+*                     Added XFL_DEVCTL_SET_CONFIG_REG IOCTL to write to the
+*                     Configuration Register of the Xilinx Platform Flash XL
+*                     which can be used to set the Flash in Sync/Async mode.
+*                     The Xilinx Platform Flash XL is set to Async mode during
+*                     the initialization of the library.
+*                     Added bank(s) reset function at the top of the read
+*                     function.
+*                     Updated Lock and Unlock operations for multiple blocks.
+* 1.03a ksu  10/07/09 Added support for large buffer size flash (CR535564)
+* 3.01a srt  03/02/12 Added support for Micron G18 Flash device to fix
+*		      CRs 648372, 648282.
+*		      Modified XFlashIntel_Reset function to reset all the
+*		      partitions.
+* 3.02a srt  05/30/12 Changed Implementation for Micron G18 Flash, which
+*		      fixes the CR 662317.
+*		      CR 662317 Description - Xilinx Platform Flash on ML605
+*		      fails to work.
+* 3.03a srt  11/04/12 Fixed CR 679937 -
+*		      Description: Non-word aligned data write to flash fails
+*		      with AXI interface.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "include/xilflash.h" + +#ifdef XPAR_XFL_DEVICE_FAMILY_INTEL +#include "include/xilflash_intel.h" +#include "include/xilflash_cfi.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/* + * Define a single type used to access the status register irregardless of the + * width of the devices + */ +typedef union { + u8 Mask8; + u16 Mask16; + u32 Mask32; + Xuint64 Mask64; +} StatReg; + +/* + * Define Intel specific data to be part of the instance. This structure will + * overlay the XFlash_PartData structure attribute of the base class. + */ +typedef struct XFlashVendorData_IntelTag { + u32 WriteBufferWordCount; /* This value is written to the WSM when + telling it how many words will be + programmed (always will be the + maximum + allowed) */ + StatReg SR_WsmReady; /* Status register bitmask for WSM ready */ + StatReg SR_LastError; /* Status register bitmask for error condition */ + + /* + * The following functions are specific to the width of the data bus and + * will be assigned during initialization. + * + * SendCmd - Writes a single command to the devices. + * SendCmdSeq - Writes two commands in successive bus cycles to the + * devices. + * WriteBuffer - Programming algorithm optimized to perform bulk writes + * to devices. + * GetStatus - Retrieve and interpret the status registers of the + * devices + * PollSR - Poll the status register of the devices until the WSM + * signals ready. + */ + void (*SendCmd) (u32 BaseAddr, u32 Offset, u32 Cmd); + void (*SendCmdSeq) (u32 BaseAddr, u32 Offset, u32 Cmd1, u32 Cmd2); + + int (*WriteBuffer) (XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); + + int (*GetStatus) (XFlash *InstancePtr, u32 Offset); + int (*PollSR) (XFlash *InstancePtr, u32 Offset); + +} XFlashVendorData_Intel; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/***************************************************************************** +* GET_PARTDATA - Type safe way to convert the base component VendorData type +* to the family specific VendorData_Intel type. +* +* Macro signature: +* +* XFlashVendorData_Intel *GET_PARTDATA(XFlash_PartData *BaseComponent) +*****************************************************************************/ +#define GET_PARTDATA(BaseComponent) \ + ((XFlashVendorData_Intel*)&((BaseComponent)->VendorData)) + +/************************** Function Prototypes ******************************/ + +static void SendCmd8(u32 BaseAddr, u32 Offset, u32 Cmd); +static void SendCmd16(u32 BaseAddr, u32 Offset, u32 Cmd); +static void SendCmd32(u32 BaseAddr, u32 Offset, u32 Cmd); +static void SendCmd64(u32 BaseAddr, u32 Offset, u32 Cmd); + +static void SendCmdSeq8(u32 BaseAddr, u32 Offset, u32 Cmd1, u32 Cmd2); +static void SendCmdSeq16(u32 BaseAddr, u32 Offset, u32 Cmd1, u32 Cmd2); +static void SendCmdSeq32(u32 BaseAddr, u32 Offset, u32 Cmd1, u32 Cmd2); +static void SendCmdSeq64(u32 BaseAddr, u32 Offset, u32 Cmd1, u32 Cmd2); + +static int GetStatus8(XFlash *InstancePtr, u32 Offset); +static int GetStatus16(XFlash *InstancePtr, u32 Offset); +static int GetStatus32(XFlash *InstancePtr, u32 Offset); +static int GetStatus64(XFlash *InstancePtr, u32 Offset); + +static int WriteBuffer8(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); +static int WriteBuffer16(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); +static int WriteBuffer32(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); +static int WriteBuffer64(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes); + +static int PollSR8(XFlash *InstancePtr, u32 Offset); +static int PollSR16(XFlash *InstancePtr, u32 Offset); +static int PollSR32(XFlash *InstancePtr, u32 Offset); +static int PollSR64(XFlash *InstancePtr, u32 Offset); + +static int SetRYBY(XFlash *InstancePtr, u32 Mode); +static void GetPartID(XFlash *InstancePtr); +static int XFlashIntel_ResetBank(XFlash *InstancePtr, u32 Offset, u32 Bytes); +static u16 EnqueueEraseBlocks(XFlash *InstancePtr, u16 *RegionPtr, + u16 *BlockPtr, u16 MaxBlocks); + +extern int XFlashGeometry_ToBlock(XFlashGeometry *InstancePtr, + u32 AbsoluteOffset, + u16 *Region, u16 *Block, u32 *BlockOffset); +extern int XFlashGeometry_ToAbsolute(XFlashGeometry *InstancePtr, + u16 Region, + u16 Block, + u32 BlockOffset, u32 *AbsoluteOffsetPtr); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Initializes a XFlash instance with device family specific details. The +* initialization entails: +* +* - Assign part access primitive functions depending on bus width. +* - Reset the device. +* +* @param InstancePtr is a pointer to the XFlash instance. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_PART_NOT_SUPPORTED if the command set algorithm or +* Layout is not supported by any specific flash device family +* compiled into the system. +* - XST_FAILURE if error. +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_Initialize(XFlash *InstancePtr) +{ + XFlashVendorData_Intel *DevDataPtr; + u32 Layout; + int BusWidthBytes; + + /* + * Verify inputs are valid + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + /* + * Grab layout and get Vendor specific part information + */ + Layout = InstancePtr->Geometry.MemoryLayout; + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Setup alignment of the write buffer. + */ + if (InstancePtr->Properties.ProgCap.WriteBufferSize != NULL) { + InstancePtr->Properties.ProgCap.WriteBufferAlignmentMask = + InstancePtr->Properties.ProgCap.WriteBufferSize - 1; + } + + + /* + * Setup layout dependent attributes. These include: + * - Part access primitive functions optimized for a specific bus + * width. + * - SR_WsmRead.MaskX is set according to the SR_WSM_READY constant + * defined as 0x80. We don't use that constant here because it is + * simpler to define with a magic number rather than use complex + * masks and shifting operations. + */ + switch (Layout) { + + case XFL_LAYOUT_X16_X8_X1: + DevDataPtr->SR_WsmReady.Mask8 = 0x80; + DevDataPtr->GetStatus = GetStatus8; + DevDataPtr->SendCmd = SendCmd8; + DevDataPtr->SendCmdSeq = SendCmdSeq8; + DevDataPtr->PollSR = PollSR8; + DevDataPtr->WriteBuffer = WriteBuffer8; + break; + + case XFL_LAYOUT_X16_X16_X1: + DevDataPtr->SR_WsmReady.Mask16 = 0x0080; + DevDataPtr->GetStatus = GetStatus16; + DevDataPtr->SendCmd = SendCmd16; + DevDataPtr->SendCmdSeq = SendCmdSeq16; + DevDataPtr->PollSR = PollSR16; + DevDataPtr->WriteBuffer = WriteBuffer16; + break; + + case XFL_LAYOUT_X16_X16_X2: + DevDataPtr->SR_WsmReady.Mask32 = 0x00800080; + DevDataPtr->GetStatus = GetStatus32; + DevDataPtr->SendCmd = SendCmd32; + DevDataPtr->SendCmdSeq = SendCmdSeq32; + DevDataPtr->PollSR = PollSR32; + DevDataPtr->WriteBuffer = WriteBuffer32; + break; + + case XFL_LAYOUT_X16_X16_X4: + DevDataPtr->SR_WsmReady.Mask32 = 0x00800080; + DevDataPtr->GetStatus = GetStatus64; + DevDataPtr->SendCmd = SendCmd64; + DevDataPtr->SendCmdSeq = SendCmdSeq64; + DevDataPtr->PollSR = PollSR64; + DevDataPtr->WriteBuffer = WriteBuffer64; + break; + + default: + return (XFLASH_PART_NOT_SUPPORTED); + } + + /* + * Calculate data written during a buffer write that tells the buffer + * how many words are going to be written to the buffer. This value is + * based on ProgCap.WriteBufferSize which was taken from the standard + * CFI query at offset 2Ah. Dividing this value by the width of the data + * bus gives us the maximum number of writes to the buffer per Intel + * literature. + */ + BusWidthBytes = (Layout & XFL_LAYOUT_NUM_PARTS_MASK) * + ((Layout & XFL_LAYOUT_PART_MODE_MASK) >> 8); + DevDataPtr->WriteBufferWordCount = + (InstancePtr->Properties.ProgCap.WriteBufferSize / + BusWidthBytes) - 1; + + /* + * Get part ID. + */ + GetPartID(InstancePtr); + + /* + * Reset the part. + */ + (void) XFlashIntel_Reset(InstancePtr); + + /* + * Zero out error data and return. + */ + XUINT64_MSW(DevDataPtr->SR_LastError.Mask64) = 0; + XUINT64_LSW(DevDataPtr->SR_LastError.Mask64) = 0; + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* The routine reads the data from the Intel flash device and copies it into +* user buffer. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from +* which to read. +* @param Bytes is the number of bytes to copy. +* @param DestPtr is the destination address to copy data to. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the source address does not start +* within the addressable areas of the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_Read(XFlash *InstancePtr, u32 Offset, u32 Bytes, void *DestPtr) +{ + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(DestPtr == NULL) { + return XST_FAILURE; + } + + /* + * Check to make sure start address is within the device. + */ + if (!XFL_GEOMETRY_IS_ABSOLUTE_VALID(&InstancePtr->Geometry, Offset)) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + if (XFlashIntel_ResetBank(InstancePtr, Offset, Bytes)!= XST_SUCCESS) { + return (XST_FAILURE); + } + + /* + * Perform copy to the user buffer from the buffer. + */ + memcpy(DestPtr, (void *) (InstancePtr->Geometry.BaseAddress + Offset), + Bytes); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Programs the Intel flash device with data stored in the user buffer. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin programming. Must be aligned to the width of the +* flash's data bus. +* @param Bytes is the number of bytes to program. +* @param SrcPtr is the source address containing data to be programmed. +* Must be aligned to the width of the flash's data bus. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. Use XFlash_DeviceControl() to +* retrieve specific error conditions. When this error is +* returned, it is possible that the target address range was +* only partially programmed. +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_Write(XFlash *InstancePtr, u32 Offset, u32 Bytes, void *SrcPtr) +{ + XFlashVendorData_Intel *DevDataPtr; + int Status; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + if(SrcPtr == NULL) { + return XST_FAILURE; + } + + /* + * Nothing specified to be programmed. + */ + if (Bytes == 0) { + return (XST_SUCCESS); + } + + /* + * Verify the address range is within the part. + */ + if (!XFL_GEOMETRY_IS_ABSOLUTE_VALID(&InstancePtr->Geometry, Offset) || + !XFL_GEOMETRY_IS_ABSOLUTE_VALID(&InstancePtr->Geometry, + Offset + Bytes - 1)) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Call the proper write buffer function. + */ + DevDataPtr = GET_PARTDATA(InstancePtr); + Status = DevDataPtr->WriteBuffer(InstancePtr, (void *) + (InstancePtr->Geometry.BaseAddress + + Offset), SrcPtr, Bytes); + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashIntel_ResetBank(InstancePtr, Offset, Bytes); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* Erases the specified address range in the Intel Flash device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin erasure. +* @param Bytes is the number of bytes to erase. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_Erase(XFlash *InstancePtr, u32 Offset, u32 Bytes) +{ + u16 StartRegion, EndRegion; + u16 StartBlock, EndBlock; + u16 BlocksLeft, BlocksQueued; + u32 Dummy; + XFlashGeometry *GeomPtr; + XFlashVendorData_Intel *DevDataPtr; + int Status; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + GeomPtr = &InstancePtr->Geometry; + + /* + * Handle case when zero bytes is provided. + */ + if (Bytes == 0) { + return (XST_SUCCESS); + } + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &StartRegion, + &StartBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Convert the ending address to block coordinates. This also verifies + * the ending address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset + Bytes - 1, + &EndRegion, &EndBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Erase loop. Queue up as many blocks at a time until all are erased. + */ + DevDataPtr = GET_PARTDATA(InstancePtr); + BlocksLeft = XFL_GEOMETRY_BLOCK_DIFF(GeomPtr, StartRegion, StartBlock, + EndRegion, EndBlock); + + while (BlocksLeft > 0) { + BlocksQueued = EnqueueEraseBlocks(InstancePtr, &StartRegion, + &StartBlock, BlocksLeft); + BlocksLeft -= BlocksQueued; + + Status = DevDataPtr->PollSR(InstancePtr, Offset); + if (Status != XFLASH_READY) { + (void) XFlashIntel_ResetBank(InstancePtr, Offset, + Bytes); + return (Status); + } + } + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashIntel_ResetBank(InstancePtr, Offset, Bytes); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Locks the blocks in the specified range of the Intel flash device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin block locking. The first three bytes of every block is +* reserved for special purpose. The offset should be atleast three +* bytes from start of the block. +* @param Bytes indicates the number of bytes to Lock in the Block +* starting from Offset. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_Lock(XFlash *InstancePtr, u32 Offset, u32 Bytes) +{ + volatile u16 StatusReg; + XFlashVendorData_Intel *DevDataPtr; + u16 StartRegion, EndRegion; + u16 StartBlock, EndBlock; + u16 Region, Block; + u16 BlocksLeft; + u32 Dummy; + u32 BaseAddress; + u32 BlockAddress; + int Status; + XFlashGeometry *GeomPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + GeomPtr = &InstancePtr->Geometry; + BaseAddress = GeomPtr->BaseAddress; + + /* + * Handle case when zero bytes is provided. + */ + if (Bytes == 0) { + /* + * Lock 1 block (for backward compatibility) + */ + Bytes = 1; + } + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &StartRegion, + &StartBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Convert the ending address to block coordinates. This also verifies + * the ending address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset + Bytes - 1, + &EndRegion, &EndBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Find total number of blocks to be locked. + */ + DevDataPtr = GET_PARTDATA(InstancePtr); + BlocksLeft = XFL_GEOMETRY_BLOCK_DIFF(GeomPtr, StartRegion, StartBlock, + EndRegion, EndBlock); + + /* + * Sample the register(s). Wait till the device is ready. + */ + DevDataPtr->SendCmd(BaseAddress, Offset, XFL_INTEL_CMD_READ_STATUS_REG); + StatusReg = READ_FLASH_16(BaseAddress + Offset); + while(!(StatusReg & XFL_INTEL_SR_WSM_READY)) { + StatusReg = READ_FLASH_8(BaseAddress + Offset); + } + + Region = StartRegion; + Block = StartBlock; + + while (BlocksLeft > 0) { + /* + * Find the block address. + */ + (void) XFlashGeometry_ToAbsolute(GeomPtr, Region, Block, 0, + &BlockAddress); + + /* + * Clear any latched status register content. + */ + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_CLEAR_STATUS_REG); + + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_LOCK_BLOCK_SET); + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_LOCK_BLOCK_SET_CONFIRM); + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_READ_STATUS_REG); + /* + * Check if the Locking is done and device is ready. + */ + StatusReg = READ_FLASH_16(BaseAddress + BlockAddress); + while(!(StatusReg & XFL_INTEL_SR_WSM_READY)) { + StatusReg = READ_FLASH_16(BaseAddress + BlockAddress); + } + + /* + * Check if any Lock error has occurred. + */ + if(StatusReg & XFL_INTEL_SR_PROG_OR_LOCK_ERROR) { + return XST_FAILURE; + } + + /* + * Increment Region/Block. + */ + XFL_GEOMETRY_INCREMENT(GeomPtr, Region, Block); + + BlocksLeft--; + } + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashIntel_ResetBank(InstancePtr, Offset, Bytes); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Unlocks the blocks in the specified range of the Intel flash device. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset into the device(s) address space from which +* to begin block UnLocking. The first three bytes of every block +* is reserved for special purpose. The offset should be atleast +* three bytes from start of the block. +* @param Bytes indicates the number of bytes to UnLock in the Block +* starting from Offset. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ADDRESS_ERROR if the destination address range is +* not completely within the addressable areas of the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_Unlock(XFlash *InstancePtr, u32 Offset, u32 Bytes) +{ + + volatile u16 StatusReg; + XFlashVendorData_Intel *DevDataPtr; + u16 StartRegion, EndRegion; + u16 StartBlock, EndBlock; + u16 Region, Block; + u16 BlocksLeft; + u32 Dummy; + u32 BaseAddress; + u32 BlockAddress; + int Status; + XFlashGeometry *GeomPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + GeomPtr = &InstancePtr->Geometry; + BaseAddress = GeomPtr->BaseAddress; + + /* + * Handle case when zero bytes is provided. + */ + if (Bytes == 0) { + /* + * Unlock 1 block (for backward compatibility) + */ + Bytes = 1; + } + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &StartRegion, + &StartBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Convert the ending address to block coordinates. This also verifies + * the ending address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset + Bytes - 1, + &EndRegion, &EndBlock, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + /* + * Find total number of blocks to be unlocked. + */ + DevDataPtr = GET_PARTDATA(InstancePtr); + BlocksLeft = XFL_GEOMETRY_BLOCK_DIFF(GeomPtr, StartRegion, StartBlock, + EndRegion, EndBlock); + + /* + * Sample the register(s). Wait till the device is ready. + */ + DevDataPtr->SendCmd(BaseAddress, Offset, XFL_INTEL_CMD_READ_STATUS_REG); + StatusReg = READ_FLASH_16(BaseAddress + Offset); + while(!(StatusReg & XFL_INTEL_SR_WSM_READY)) { + StatusReg = READ_FLASH_8(BaseAddress + Offset); + } + + Region = StartRegion; + Block = StartBlock; + + while (BlocksLeft > 0) { + /* + * Find the block address. + */ + (void) XFlashGeometry_ToAbsolute(GeomPtr, Region, Block, 0, + &BlockAddress); + + /* + * Clear any latched status register content. + */ + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_CLEAR_STATUS_REG); + + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_LOCK_BLOCK_CLEAR); + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_LOCK_BLOCK_CLEAR_CONFIRM); + DevDataPtr->SendCmd(BaseAddress, BlockAddress, + XFL_INTEL_CMD_READ_STATUS_REG); + + /* + * Check if the Unlocking is done and device is ready. + */ + StatusReg = READ_FLASH_16(BaseAddress + BlockAddress); + while(!(StatusReg & XFL_INTEL_SR_WSM_READY)) { + StatusReg = READ_FLASH_16(BaseAddress + BlockAddress); + } + + /* + * Check if any Unlock error has occurred. + */ + if(StatusReg & XFL_INTEL_SR_ERASE_OR_UNLOCK_ERROR) { + return XST_FAILURE; + } + + /* + * Increment Region/Block. + */ + XFL_GEOMETRY_INCREMENT(GeomPtr, Region, Block); + + BlocksLeft--; + } + + /* + * Reset the bank(s) so that it returns to the read mode. + */ + (void) XFlashIntel_ResetBank(InstancePtr, Offset, Bytes); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Clears the Intel flash device status register(s) and place the device(s) into +* read mode. +* +* @param InstancePtr is the pointer to the XFlash instance. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_BUSY if the flash devices were in the middle of an +* operation and could not be reset. +* - XFLASH_ERROR if the device(s) have experienced an internal +* error during the operation. XFlash_DeviceControl() must be +* used to access the cause of the device specific error +* condition. +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_Reset(XFlash *InstancePtr) +{ + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + /* + * Send reset for all region/bank(s) in the device. + */ + return (XFlashIntel_ResetBank(InstancePtr, 0, + InstancePtr->Geometry.DeviceSize)); + +} + +/*****************************************************************************/ +/** +* +* Clears the Intel flash bank status register and place the bank into read mode. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the bank address. +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_BUSY if the flash bank were in the middle of an +* operation and could not be reset. +* - XFLASH_ERROR if the bank have experienced an internal error +* during the operation. XFlash_DeviceControl() must be used to +* access the cause of the device specific error condition. +* +* @note None. +* +******************************************************************************/ +static int XFlashIntel_ResetBank(XFlash *InstancePtr, u32 Offset, u32 Bytes) +{ + XFlashVendorData_Intel *DevDataPtr; + int Status; + u16 Region, Block; + u32 BaseAddress; + u32 Dummy; + XFlashGeometry *GeomPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + /* + * Handle case when zero bytes is provided. + */ + if (Bytes == 0) { + return XST_SUCCESS; + } + + GeomPtr = &InstancePtr->Geometry; + BaseAddress = GeomPtr->BaseAddress; + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Convert the starting address to block coordinates. This also verifies + * the starting address is within the instance's address space. + */ + Status = XFlashGeometry_ToBlock(GeomPtr, Offset, &Region, + &Block, &Dummy); + if (Status != XST_SUCCESS) { + return (XFLASH_ADDRESS_ERROR); + } + + + while ((GeomPtr->EraseRegion[Region].AbsoluteOffset <= + (Offset + Bytes - 1)) && + (Region < InstancePtr->Geometry.NumEraseRegions)) { + /* + * Send the clear status register command. Use the max write + * width to notify parts of all layouts. + */ + DevDataPtr->SendCmd(BaseAddress, + GeomPtr->EraseRegion[Region].AbsoluteOffset, + XFL_INTEL_CMD_CLEAR_STATUS_REG); + DevDataPtr->SendCmd(BaseAddress, + GeomPtr->EraseRegion[Region].AbsoluteOffset, + XFL_INTEL_CMD_READ_STATUS_REG); + + /* + * Sample the status of the parts, then place them into + * read-array mode. + */ + Status = DevDataPtr->GetStatus(InstancePtr, + GeomPtr->EraseRegion[Region].AbsoluteOffset); + + /* + * Some Intel CFI chips support 0xF0 command instead of 0xFF as + * reset/read array command. + */ + DevDataPtr->SendCmd(BaseAddress, + GeomPtr->EraseRegion[Region].AbsoluteOffset, + XFL_INTEL_CMD_RESET_0xF0); + DevDataPtr->SendCmd(BaseAddress, + GeomPtr->EraseRegion[Region].AbsoluteOffset, + XFL_INTEL_CMD_READ_ARRAY); + + /* + * If the status is not ready, then something is wrong. + */ + if (Status != XFLASH_READY) { + if (Status != XFLASH_BUSY) { + return (XFLASH_ERROR); + } + else { + return (XFLASH_BUSY); + } + } + + /* + * Increment the region/bank. + */ + Region++; + } + + return (XST_SUCCESS); +} + + +/*****************************************************************************/ +/** +* +* Performs the Intel device specific control functions. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Command is the device specific command to issue. +* @param Parameters specifies the arguments passed to the device control +* function. +* +* @return +* - XST_SUCCESS if successful +* - XFLASH_NOT_SUPPORTED if the command is not +* recognized/supported by the device(s). +* +* @note None. +* +******************************************************************************/ +int XFlashIntel_DeviceControl(XFlash *InstancePtr, u32 Command, + DeviceCtrlParam *Parameters) +{ + int Status; + XFlashVendorData_Intel *DevDataPtr; + + /* + * Verify inputs are valid. + */ + if(InstancePtr == NULL) { + return XST_FAILURE; + } + + DevDataPtr = GET_PARTDATA(InstancePtr); + + switch (Command) { + case XFL_DEVCTL_GET_LAST_ERROR: + Parameters->LastErrorParam.Error = + DevDataPtr->SR_LastError.Mask32; + return (XST_SUCCESS); + + case XFL_DEVCTL_GET_GEOMETRY: + Parameters->GeometryParam.GeometryPtr = + &InstancePtr->Geometry; + return XST_SUCCESS; + + case XFL_DEVCTL_GET_PROPERTIES: + Parameters->PropertiesParam.PropertiesPtr = + &InstancePtr->Properties; + return XST_SUCCESS; + + case XFL_DEVCTL_SET_RYBY: + if (InstancePtr->Properties.PartID.CommandSet != + XFL_CMDSET_INTEL_EXTENDED) { + return (XFLASH_NOT_SUPPORTED); + } + + Status = SetRYBY(InstancePtr, + Parameters->RyByParam.Param); + return (Status); + + case XFL_DEVCTL_SET_CONFIG_REG: + if (InstancePtr->IsPlatformFlash == 1) { + DevDataPtr->SendCmdSeq( + InstancePtr->Geometry.BaseAddress, + Parameters->ConfigRegParam.Value, + XFL_INTEL_CMD_CONFIG_REG_SETUP, + XFL_INTEL_CMD_CONFIG_REG_CONFIRM); + return (XST_SUCCESS); + } + + return (XFLASH_NOT_SUPPORTED); + + default: + return (XFLASH_NOT_SUPPORTED); + } +} + +/*****************************************************************************/ +/** +* +* Retrieves and interprets status register data from part arrays that occupy a +* 8-bit bus. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return +* - XFLASH_READY if the flash device is ready. +* - XFLASH_BUSY if the flash device is Busy. +* - XFLASH_ERROR if some error has occurred during flash +* operation. +* +* @note No attempt is made to determine the exact cause of an error. +* Instead that determination is left up to the user. +* +******************************************************************************/ +static int GetStatus8(XFlash *InstancePtr, u32 Offset) +{ + u8 RegData; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Sample the register(s). + */ + RegData = READ_FLASH_8(InstancePtr->Geometry.BaseAddress + Offset); + + /* + * First determine if the device(s) are ready without errors indicated. + */ + if (RegData == DevDataPtr->SR_WsmReady.Mask8) { + return (XFLASH_READY); + } + + /* + * Next determine if the device(s) are still busy. + */ + if ((RegData & DevDataPtr->SR_WsmReady.Mask8) != + DevDataPtr->SR_WsmReady.Mask8) { + return (XFLASH_BUSY); + } + + /* + * If control reaches this point, then an error is pending. Copy the + * entire set of registers to the SR_LastError attribute. + */ + DevDataPtr->SR_LastError.Mask8 = RegData; + + return (XFLASH_ERROR); +} + +/*****************************************************************************/ +/** +* +* Retrieves and interprets status register data from part arrays that occupy a +* 16-bit bus. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return +* - XFLASH_READY if the flash device is ready. +* - XFLASH_BUSY if the flash device is Busy. +* - XFLASH_ERROR if some error has occurred during flash +* operation. +* +* @note No attempt is made to determine the exact cause of an error. +* Instead that determination is left up to the user. +* +******************************************************************************/ +static int GetStatus16(XFlash *InstancePtr, u32 Offset) +{ + u16 RegData; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Sample the register(s). + */ + RegData = READ_FLASH_16(InstancePtr->Geometry.BaseAddress + Offset); + + /* + * First determine if the device(s) are ready without errors indicated. + */ + if (RegData == DevDataPtr->SR_WsmReady.Mask16) { + return (XFLASH_READY); + } + + /* + * Next determine if the device(s) are still busy. + */ + if ((RegData & DevDataPtr->SR_WsmReady.Mask16) != + DevDataPtr->SR_WsmReady.Mask16) { + return (XFLASH_BUSY); + } + + /* + * If control reaches this point, then an error is pending. Copy the + * entire set of registers to the SR_LastError attribute. + */ + DevDataPtr->SR_LastError.Mask16 = RegData; + + return (XFLASH_ERROR); +} + +/*****************************************************************************/ +/** +* +* Retrieves and interprets status register data from part arrays that occupy a +* 32-bit bus. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return +* - XFLASH_READY if the flash device is ready. +* - XFLASH_BUSY if the flash device is Busy. +* - XFLASH_ERROR if some error has occurred during flash +* operation. +* +* @note No attempt is made to determine the exact cause of an error. +* Instead that determination is left up to the user. +* +******************************************************************************/ +static int GetStatus32(XFlash *InstancePtr, u32 Offset) +{ + u32 RegData; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Sample the register(s). + */ + RegData = READ_FLASH_32(InstancePtr->Geometry.BaseAddress + Offset); + + /* + * First, determine if the device(s) are ready without errors indicated. + */ + if (RegData == DevDataPtr->SR_WsmReady.Mask32) { + return (XFLASH_READY); + } + + /* + * Next, determine if the device(s) are still busy. + */ + if ((RegData & DevDataPtr->SR_WsmReady.Mask32) != + DevDataPtr->SR_WsmReady.Mask32) { + return (XFLASH_BUSY); + } + + /* + * If control reaches this point, then an error is pending. Copy the + * entire set of registers to the SR_LastError attribute. + */ + DevDataPtr->SR_LastError.Mask32 = RegData; + + return (XFLASH_ERROR); +} + +/*****************************************************************************/ +/** +* +* Retrieves and interprets status register data from part arrays that occupy a +* 64-bit bus. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return +* - XFLASH_READY if the flash device is ready. +* - XFLASH_BUSY if the flash device is Busy. +* - XFLASH_ERROR if some error has occurred during flash +* operation. +* +* @note No attempt is made to determine the exact cause of an error. +* Instead that determination is left up to the user. +* +******************************************************************************/ +static int GetStatus64(XFlash *InstancePtr, u32 Offset) +{ + Xuint64 RegData; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Sample the status register(s) and OR the 32 bit halves together. + */ + READ_FLASH_64(InstancePtr->Geometry.BaseAddress + Offset, RegData); + + /* + * First, determine if the device(s) are ready without errors indicated. + */ + if ((XUINT64_MSW(RegData) == DevDataPtr->SR_WsmReady.Mask32) && + (XUINT64_LSW(RegData) == DevDataPtr->SR_WsmReady.Mask32)) { + return (XFLASH_READY); + } + + /* + * Next, determine if the device(s) are still busy. + */ + if (((XUINT64_MSW(RegData) & DevDataPtr->SR_WsmReady.Mask32) != + DevDataPtr->SR_WsmReady.Mask32) && ((XUINT64_LSW(RegData) + & DevDataPtr->SR_WsmReady. + Mask32) != + DevDataPtr->SR_WsmReady. + Mask32)) { + return (XFLASH_BUSY); + } + + /* + * If control reaches this point, then an error is pending. Copy the + * entire set of registers to the SR_LastError attribute. + */ + XUINT64_MSW(DevDataPtr->SR_LastError.Mask64) = XUINT64_MSW(RegData); + XUINT64_LSW(DevDataPtr->SR_LastError.Mask64) = XUINT64_LSW(RegData); + + return (XFLASH_ERROR); +} + +/*****************************************************************************/ +/** +* +* Polls the status register until the WSM is ready. The device(s) are polled +* by repeatedly reading the status register. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return - XFLASH_READY if WSM is ready. +* - XFLASH_ERROR if WSM is ready, but an error condition +* exists. +* +* @note For Intel parts, the status register can be accessed from any +* addressable location in the bank, in command mode. So we pick +* the address where operation was performed. +* +******************************************************************************/ +static int PollSR8(XFlash *InstancePtr, u32 Offset) +{ + u8 StatusReg; + u8 ReadyMask; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Wait until WSM indicates that it is complete. + */ + ReadyMask = DevDataPtr->SR_WsmReady.Mask8; + StatusReg = READ_FLASH_8(InstancePtr->Geometry.BaseAddress + Offset); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_8(InstancePtr->Geometry.BaseAddress + + Offset); + } + + /* + * WSM is ready, see if an error bit is set. + */ + if (StatusReg != ReadyMask) { + DevDataPtr->SR_LastError.Mask8 = StatusReg; + return (XFLASH_ERROR); + } + else { + return (XFLASH_READY); + } +} + +/*****************************************************************************/ +/** +* +* Polls the status register until the WSM is ready. The device(s) are polled +* by repeatedly reading the status register. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return - XFLASH_READY if WSM is ready. +* - XFLASH_ERROR if WSM is ready, but an error condition +* exists. +* +* @note For Intel parts, the status register can be accessed from any +* addressable location in the bank, in command mode. So we pick +* the address where operation was performed. +* +******************************************************************************/ +static int PollSR16(XFlash *InstancePtr, u32 Offset) +{ + u16 StatusReg; + u16 ReadyMask; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Wait until WSM indicates that it is complete. + */ + ReadyMask = DevDataPtr->SR_WsmReady.Mask16; + StatusReg = READ_FLASH_16(InstancePtr->Geometry.BaseAddress + Offset); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_16(InstancePtr->Geometry.BaseAddress + + Offset); + } + + /* + * WSM is ready, see if an error bit is set. + */ + if (StatusReg != ReadyMask) { + DevDataPtr->SR_LastError.Mask16 = StatusReg; + return (XFLASH_ERROR); + } + else { + return (XFLASH_READY); + } +} + +/*****************************************************************************/ +/** +* +* Polls the status register until the WSM is ready. The +* device(s) are polled by repeatedly reading the status register. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return - XFLASH_READY if WSM is ready. +* - XFLASH_ERROR if WSM is ready, but an error condition +* exists. +* +* @note For Intel parts, the status register can be accessed from any +* addressable location in the bank, in command mode. So we pick +* the address where operation was performed. +* +******************************************************************************/ +static int PollSR32(XFlash *InstancePtr, u32 Offset) +{ + u32 StatusReg; + u32 ReadyMask; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Wait until WSM indicates that it is complete. + */ + ReadyMask = DevDataPtr->SR_WsmReady.Mask32; + StatusReg = READ_FLASH_32(InstancePtr->Geometry.BaseAddress + Offset); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_32(InstancePtr->Geometry.BaseAddress + + Offset); + } + + /* + * WSM is ready, see if an error bit is set. + */ + if (StatusReg != ReadyMask) { + DevDataPtr->SR_LastError.Mask32 = StatusReg; + return (XFLASH_ERROR); + } + else { + return (XFLASH_READY); + } +} + +/*****************************************************************************/ +/** +* +* Polls the status register until the WSM is ready. The device(s) are polled +* by repeatedly reading the status register. +* +* @param InstancePtr is the pointer to the XFlash instance. +* @param Offset is the offset address in the flash device. +* +* @return - XFLASH_READY if WSM is ready. +* - XFLASH_ERROR if WSM is ready, but an error condition +* exists. +* +* @note For Intel parts, the status register can be accessed from any +* addressable location in the bank, in command mode. So we pick +* the address where operation was performed. +* +******************************************************************************/ +static int PollSR64(XFlash *InstancePtr, u32 Offset) +{ + Xuint64 StatusReg; + u32 ReadyMask; + XFlashVendorData_Intel *DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Wait until WSM indicates that it is complete. + */ + ReadyMask = DevDataPtr->SR_WsmReady.Mask32; + READ_FLASH_64(InstancePtr->Geometry.BaseAddress + Offset, StatusReg); + while (((XUINT64_MSW(StatusReg) & ReadyMask) != ReadyMask) || + ((XUINT64_LSW(StatusReg) & ReadyMask) != ReadyMask)) { + READ_FLASH_64(InstancePtr->Geometry.BaseAddress + Offset, + StatusReg); + } + + /* + * WSM is ready, see if an error bit is set. + */ + if ((XUINT64_MSW(StatusReg) != ReadyMask) || + (XUINT64_LSW(StatusReg) != ReadyMask)) { + XUINT64_MSW(DevDataPtr->SR_LastError.Mask64) = + XUINT64_MSW(StatusReg); + XUINT64_LSW(DevDataPtr->SR_LastError.Mask64) = + XUINT64_LSW(StatusReg); + return (XFLASH_ERROR); + } + else { + return (XFLASH_READY); + } +} + +/*****************************************************************************/ +/** +* +* Writes a command using a 8-bit bus cycle. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd is the command/data to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmd8(u32 BaseAddress, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_8(BaseAddress + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command using a 16-bit bus cycle. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd is the command/data to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmd16(u32 BaseAddress, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_16(BaseAddress + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command using a 32-bit bus cycle. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd is the command/data to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmd32(u32 BaseAddress, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_32(BaseAddress + Offset, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command using a 64-bit bus cycle. Depending on the architecture, +* this may be a single write or two 32 bit writes. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd is the command/data to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmd64(u32 BaseAddress, u32 Offset, u32 Cmd) +{ + WRITE_FLASH_64x2(BaseAddress + Offset, Cmd, Cmd); +} + +/*****************************************************************************/ +/** +* +* Writes a command sequence using 8-bit bus cycles. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd1 is the first command to write at BaseAddress + Offset +* @param Cmd2 is the second command to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmdSeq8(u32 BaseAddress, u32 Offset, u32 Cmd1, u32 Cmd2) +{ + WRITE_FLASH_8(BaseAddress + Offset, Cmd1); + WRITE_FLASH_8(BaseAddress + Offset, Cmd2); +} + +/*****************************************************************************/ +/** +* +* Writes a command sequence using 16-bit bus cycles. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd1 is the first command to write at BaseAddress + Offset +* @param Cmd2 is the second command to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmdSeq16(u32 BaseAddress, u32 Offset, u32 Cmd1, u32 Cmd2) +{ + WRITE_FLASH_16(BaseAddress + Offset, Cmd1); + WRITE_FLASH_16(BaseAddress + Offset, Cmd2); +} + + +/*****************************************************************************/ +/** +* +* Writes a command sequence using 32-bit bus cycles. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd1 is the first command to write at BaseAddress + Offset +* @param Cmd2 is the second command to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmdSeq32(u32 BaseAddress, u32 Offset, u32 Cmd1, u32 Cmd2) +{ + WRITE_FLASH_32(BaseAddress + Offset, Cmd1); + WRITE_FLASH_32(BaseAddress + Offset, Cmd2); +} + +/*****************************************************************************/ +/** +* +* Writes a command sequence using 64-bit bus cycles. Depending on the +* architecture, this may be a single write or two 32 bit writes. +* +* @param BaseAddress is the base address of device +* @param Offset is the offset into device +* @param Cmd1 is the first command to write at BaseAddress + Offset +* @param Cmd2 is the second command to write at BaseAddress + Offset +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void SendCmdSeq64(u32 BaseAddress, u32 Offset, u32 Cmd1, u32 Cmd2) +{ + WRITE_FLASH_64x2(BaseAddress + Offset, Cmd1, Cmd1); + WRITE_FLASH_64x2(BaseAddress + Offset, Cmd2, Cmd2); +} + +/*****************************************************************************/ +/** +* +* Program the device(s) using the faster write to buffer mechanism. The +* device(s) are programmed in parallel. +* +* @param InstancePtr is the instance to work on +* @param DestPtr is the physical destination address in flash memory +* space +* @param SrcPtr is the source data +* @param Bytes is the number of bytes to program +* +* @return +* +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. Use XFlash_DeviceControl() to +* retrieve specific error conditions. When this error is +* returned, it is possible that the target address range was +* only partially programmed. +* +* @note +* +* This algorithm programs only full buffers at a time and must take care +* of the following situations: +* - Partial first buffer programming with pre and/or post padding +* required. +* - Multiple full buffer programming. +* - Partial last buffer programming with post padding. +*

+* When padding, 0xFF is written to each byte to be padded. This in effect does +* nothing to the current contents of the flash memory and saves us from having +* to merge real flash data with user data on partial buffer writes. +*

+* If hardware is failing, then this routine could get stuck in an endless loop. +* +******************************************************************************/ +static int WriteBuffer8(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes) +{ + XFlashVendorData_Intel *DevDataPtr; + u8 *SrcWordPtr = (u8*)SrcPtr; + u8 *DestWordPtr = (u8*)DestPtr; + u8 StatusReg; + u8 ReadyMask; + u32 BytesLeft = Bytes; + u32 BaseAddress; + u32 PartialBytes; + u32 Count; + int Status = XST_SUCCESS; + int Index; + + DevDataPtr = GET_PARTDATA(InstancePtr); + BaseAddress = InstancePtr->Geometry.BaseAddress; + ReadyMask = DevDataPtr->SR_WsmReady.Mask8; + + /* + * Determine if a partial first buffer must be programmed. + */ + PartialBytes = (u32) DestWordPtr & + InstancePtr->Properties.ProgCap.WriteBufferAlignmentMask; + + /* + * This write cycle programs the first partial write buffer. + */ + if (PartialBytes) { + /* + * Backup DestWord to the beginning of a buffer alignment area + * Count is the number of write cycles left after pre-filling + * the write buffer with 0xFFFF. + */ + DestWordPtr = (u8*)((u32) DestWordPtr - PartialBytes); + Count = InstancePtr->Properties.ProgCap.WriteBufferSize; + + /* + * Send command to write buffer. Wait for buffer to become + * available. Write number of words to be written (always the + * maximum). + */ + WRITE_FLASH_8(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + + StatusReg = READ_FLASH_8(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_8(DestWordPtr); + + } + + WRITE_FLASH_8(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Write 0xFFFF padding until we get to the start of the + * original DestWord. + */ + while (PartialBytes > 1) { + WRITE_FLASH_8(DestWordPtr++, 0xFFFF); + PartialBytes -= 1; + Count--; + } + + /* + * Write the remainder of this write buffer. + */ + Index = 0; + while (Count--) { + /* + * Write Byte + */ + if (BytesLeft >= 1) { + WRITE_FLASH_8(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 1; + } + + /* + * End of SrcWords + */ + else { + WRITE_FLASH_8(&DestWordPtr[Index], 0xFF); + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_8(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR8(InstancePtr, ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination to next buffer + */ + SrcWordPtr += Index; + DestWordPtr += Index; + } + + /* + * At this point DestWordPtr and SrcWordPtr are aligned to a write + * buffer boundary. The next batch of writes utilize write cycles full + * of SrcData. + */ + Count = InstancePtr->Properties.ProgCap.WriteBufferSize; + while (BytesLeft >= InstancePtr->Properties.ProgCap.WriteBufferSize) { + + /* + * Send command to write buffer. Wait for buffer to become + * available. Write number of words to be written (always the + * maximum). + */ + WRITE_FLASH_8(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + StatusReg = READ_FLASH_8(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_8(DestWordPtr); + } + WRITE_FLASH_8(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer + */ + for (Index = 0; Index < Count; Index++) { + WRITE_FLASH_8(&DestWordPtr[Index], SrcWordPtr[Index]); + BytesLeft -= 1; + } + + /* + * Send confirmation and wait for status + */ + WRITE_FLASH_8(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR8(InstancePtr, ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination. + */ + SrcWordPtr += Count; + DestWordPtr += Count; + } + + /* + * The last phase is to write a partial last buffer. + */ + if (BytesLeft) { + + /* + * Send command to write buffer. Wait for buffer to become + * available. Write number of words to be written (always the + * maximum). + */ + WRITE_FLASH_8(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + + StatusReg = READ_FLASH_8(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_8(DestWordPtr); + } + + WRITE_FLASH_8(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer + */ + Index = 0; + while (Count--) { + /* + * Write Byte + */ + if (BytesLeft >= 1) { + WRITE_FLASH_8(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 1; + } + + /* + * End of SrcWords + */ + else { + WRITE_FLASH_8(&DestWordPtr[Index], 0xFF); + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_8(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR8(InstancePtr, ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Program the device(s) using the faster write to buffer mechanism. The +* device(s) are programmed in parallel. +* +* @param InstancePtr is the instance to work on +* @param DestPtr is the physical destination address in flash memory +* space +* @param SrcPtr is the source data +* @param Bytes is the number of bytes to program +* +* @return +* +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. Use XFlash_DeviceControl() to +* retrieve specific error conditions. When this error is +* returned, it is possible that the target address range was +* only partially programmed. +* - XFLASH_ALIGNMENT_ERROR if the source and destination pointers +* are not aligned to a 16-bit word. +* @note +* +* This algorithm programs only full buffers at a time and must take care +* of the following situations: +* - Partial first buffer programming with pre and/or post padding +* required. +* - Multiple full buffer programming. +* - Partial last buffer programming with post padding. +*

+* When padding, 0xFF is written to each byte to be padded. This in effect does +* nothing to the current contents of the flash memory and saves us from having +* to merge real flash data with user data on partial buffer writes. +*

+* If hardware is failing, then this routine could get stuck in an endless loop. +* +******************************************************************************/ +static int WriteBuffer16(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes) +{ + XFlashVendorData_Intel *DevDataPtr; + u16 *SrcWordPtr = (u16*)SrcPtr; + u16 *DestWordPtr = (u16*)DestPtr; + u16 StatusReg; + u16 ReadyMask; + u32 BaseAddress; + u32 BytesLeft = Bytes; + u32 PartialBytes; + u32 Count; + int Status = XST_SUCCESS; + int Index; + + DevDataPtr = GET_PARTDATA(InstancePtr); + BaseAddress = InstancePtr->Geometry.BaseAddress; + ReadyMask = DevDataPtr->SR_WsmReady.Mask16; + + /* + * Make sure DestPtr and SrcPtr are aligned to a 16-bit word. + */ + if (((int) SrcWordPtr & 1) || ((int) DestWordPtr & 1)) { + return (XFLASH_ALIGNMENT_ERROR); + } + + /* + * Determine if a partial first buffer must be programmed. + */ + PartialBytes = (u32) DestWordPtr & + InstancePtr->Properties.ProgCap.WriteBufferAlignmentMask; + + /* + * This write cycle programs the first partial write buffer. + */ + if (PartialBytes) { + /* + * Backup DestWord to the beginning of a buffer alignment area + * Count is the number of write cycles left after pre-filling + * the write buffer with 0xFFFF. + */ + DestWordPtr = (u16*)((u32) DestWordPtr - PartialBytes); + Count = InstancePtr->Properties.ProgCap.WriteBufferSize >> 1; + + /* + * Send command to write buffer. Wait for buffer to become + * available. Write number of words to be written (always the + * maximum). + */ + WRITE_FLASH_16(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + + StatusReg = READ_FLASH_16(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_16(DestWordPtr); + + } + + WRITE_FLASH_16(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Write 0xFFFF padding until we get to the start of the + * original DestWord. + */ + while (PartialBytes > 1) { + WRITE_FLASH_16(DestWordPtr++, 0xFFFF); + PartialBytes -= 2; + Count--; + } + + /* + * Write the remainder of this write buffer. + */ + Index = 0; + while (Count--) { + /* Full word */ + if (BytesLeft > 1) { + WRITE_FLASH_16(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 2; + } + + /* End of SrcWords */ + else if (BytesLeft == 0) { + WRITE_FLASH_16(&DestWordPtr[Index], 0xFFFF); + } + + /* Partial word */ + else { /* BytesLeft == 1 */ + #ifdef XPAR_AXI_EMC + WRITE_FLASH_16(&DestWordPtr[Index], + 0xFF00 | SrcWordPtr[Index]); + #else + WRITE_FLASH_16(&DestWordPtr[Index], + 0x00FF | SrcWordPtr[Index]); + #endif + BytesLeft--; + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_16(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR16(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination to next buffer + */ + SrcWordPtr += Index; + DestWordPtr += Index; + } + + /* + * At this point DestWordPtr and SrcWordPtr are aligned to a write + * buffer boundary. The next batch of writes utilize write cycles full + * of SrcData. + */ + Count = InstancePtr->Properties.ProgCap.WriteBufferSize >> 1; + while (BytesLeft > InstancePtr->Properties.ProgCap.WriteBufferSize) { + + /* + * Send command to write buffer. Wait for buffer to become + * available. Write number of words to be written (always the + * maximum). + */ + WRITE_FLASH_16(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + StatusReg = READ_FLASH_16(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_16(DestWordPtr); + } + WRITE_FLASH_16(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer + */ + for (Index = 0; Index < Count; Index++) { + WRITE_FLASH_16(&DestWordPtr[Index], SrcWordPtr[Index]); + BytesLeft -= 2; + } + + /* + * Send confirmation and wait for status + */ + WRITE_FLASH_16(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR16(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination. + */ + SrcWordPtr += Count; + DestWordPtr += Count; + } + + /* + * The last phase is to write a partial last buffer. + */ + if (BytesLeft) { + + /* + * Send command to write buffer. Wait for buffer to become + * available. Write number of words to be written (always the + * maximum). + */ + WRITE_FLASH_16(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + + StatusReg = READ_FLASH_16(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_16(DestWordPtr); + } + + WRITE_FLASH_16(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer + */ + Index = 0; + while (Count--) { + /* + * Full word. + */ + if (BytesLeft > 1) { + WRITE_FLASH_16(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 2; + } + + /* End of SrcWords */ + else if (BytesLeft == 0) { + WRITE_FLASH_16(&DestWordPtr[Index], 0xFFFF); + } + /* Partial word */ + else { /* BytesLeft == 1 */ + + #ifdef XPAR_AXI_EMC + WRITE_FLASH_16(&DestWordPtr[Index], + 0xFF00 | SrcWordPtr[Index]); + #else + WRITE_FLASH_16(&DestWordPtr[Index], + 0x00FF | SrcWordPtr[Index]); + #endif + BytesLeft--; + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_16(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR16(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Programs the device(s) using the faster write to buffer mechanism. The +* device(s) are programmed in parallel. +* +* @param InstancePtr is the instance to work on +* @param DestPtr is the physical destination address in flash memory +* space +* @param SrcPtr is the source data +* @param Bytes is the number of bytes to program +* +* @return +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. Use XFlash_DeviceControl() to +* retrieve specific error conditions. When this error is +* returned, it is possible that the target address range was +* only partially programmed. +* - XFLASH_ALIGNMENT_ERROR if the source and destination pointers +* are not aligned to a 16-bit word. +* +* @note +* +* This algorithm programs only full buffers at a time and must take care +* of the following situations: +* - Partial first buffer programming with pre and/or post padding +* required. +* - Multiple full buffer programming. +* - Partial last buffer programming with post padding. +*

+* When padding, 0xFF is written to each byte to be padded. This in effect does +* nothing to the current contents of the flash memory and saves us from having +* to merge real flash data with user data on partial buffer writes. +*

+* If hardware is failing, then this routine could get stuck in an endless loop. +* +******************************************************************************/ +static int WriteBuffer32(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes) +{ + XFlashVendorData_Intel *DevDataPtr; + u32 *SrcWordPtr = (u32*)SrcPtr; + u32 *DestWordPtr = (u32*)DestPtr; + u32 StatusReg; + u32 ReadyMask; + u32 BaseAddress; + u32 BytesLeft = Bytes; + u32 PartialBytes; + u32 Count; + int Status = XST_SUCCESS; + int Index; + + DevDataPtr = GET_PARTDATA(InstancePtr); + BaseAddress = InstancePtr->Geometry.BaseAddress; + ReadyMask = DevDataPtr->SR_WsmReady.Mask32; + + /* + * Make sure DestPtr and SrcPtr are aligned to a 32-bit word. + */ + if (((int) SrcWordPtr & 3) || ((int) DestWordPtr & 3)) { + return (XFLASH_ALIGNMENT_ERROR); + } + + /* + * Determine if a partial first buffer must be programmed. + */ + PartialBytes = (u32) DestWordPtr & + InstancePtr->Properties.ProgCap.WriteBufferAlignmentMask; + + /* + * This write cycle programs the first partial write buffer. + */ + if (PartialBytes) { + + /* + * Backup DestWord to the beginning of a buffer alignment area + * Count is the number of write cycles left after pre-filling + * the write buffer with 0xFFFF. + */ + DestWordPtr = (u32*)((u32) DestWordPtr - PartialBytes); + Count = InstancePtr->Properties.ProgCap.WriteBufferSize >> 2; + + /* + * Send command to write buffer. Wait for buffer to become + * available. + * Write number of words to be written (always the maximum). + */ + WRITE_FLASH_32(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + StatusReg = READ_FLASH_32(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_32(DestWordPtr); + } + WRITE_FLASH_32(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Write 0xFFFFFFFF padding until we get to the start of the + * user data. + */ + while (PartialBytes > 3) { + WRITE_FLASH_32(DestWordPtr++, 0xFFFFFFFF); + PartialBytes -= 4; + Count--; + } + + /* + * Write the remainder of this write buffer. + */ + Index = 0; + while (Count--) { + /* Full word */ + if (BytesLeft > 3) { + WRITE_FLASH_32(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 4; + } + + /* End of SrcWords */ + else if (BytesLeft == 0) { + WRITE_FLASH_32(&DestWordPtr[Index], 0xFFFFFFFF); + } + + /* Partial word */ + else if (BytesLeft == 1) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFFFF00 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x00FFFFFF | SrcWordPtr[Index]); + #endif + BytesLeft--; + } + else if (BytesLeft == 2) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFF0000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x0000FFFF | SrcWordPtr[Index]); + #endif + BytesLeft -= 2; + } + else { /* BytesLeft == 3 */ + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFF000000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x000000FF | SrcWordPtr[Index]); + #endif + BytesLeft -= 3; + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_32(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR32(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination to last access position. + */ + SrcWordPtr += Index; + DestWordPtr += Index; + } + + /* + * At this point DestPtr and SrcPtr are aligned to a write buffer + * boundary. + * The next batch of writes utilize a write cycle full of SrcData. + */ + Count = InstancePtr->Properties.ProgCap.WriteBufferSize >> 2; + while (BytesLeft >= InstancePtr->Properties.ProgCap.WriteBufferSize) { + + /* + * Send command to write buffer. Wait for buffer to become + * available. + * Write number of words to be written (always the maximum). + */ + WRITE_FLASH_32(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + StatusReg = READ_FLASH_32(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_32(DestWordPtr); + } + + WRITE_FLASH_32(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer. + */ + for (Index = 0; Index < Count; Index++) { + WRITE_FLASH_32(&DestWordPtr[Index], SrcWordPtr[Index]); + BytesLeft -= 4; + } + + /* + * Send confirmation and wait for status. + */ + WRITE_FLASH_32(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR32(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination. + */ + SrcWordPtr += Count; + DestWordPtr += Count; + } + + /* + * The last phase is to write a partial last write buffer. + */ + if (BytesLeft) { + /* + * Send command to write buffer. Wait for buffer to become + * available. + * Write number of words to be written (always the maximum). + */ + WRITE_FLASH_32(DestWordPtr, + InstancePtr->Command.WriteBufferCommand); + StatusReg = READ_FLASH_32(DestWordPtr); + while ((StatusReg & ReadyMask) != ReadyMask) { + StatusReg = READ_FLASH_32(DestWordPtr); + } + WRITE_FLASH_32(DestWordPtr, DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer. + */ + Index = 0; + while (Count--) { + /* + * Full word. + */ + if (BytesLeft > 3) { + WRITE_FLASH_32(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 4; + } + + /* End of SrcWords */ + else if (BytesLeft == 0) { + WRITE_FLASH_32(&DestWordPtr[Index], 0xFFFFFFFF); + } + + /* Partial word */ + else if (BytesLeft == 1) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFFFF00 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x00FFFFFF | SrcWordPtr[Index]); + #endif + BytesLeft--; + } + else if (BytesLeft == 2) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFF0000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x0000FFFF | SrcWordPtr[Index]); + #endif + BytesLeft -= 2; + } + else { /* BytesLeft == 3 */ + + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFF000000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x000000FF | SrcWordPtr[Index]); + #endif + BytesLeft -= 3; + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_32(DestWordPtr, XFL_INTEL_CMD_CONFIRM); + Status = PollSR32(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Programs the device(s) using the faster write to buffer mechanism. The +* device(s) are programmed in parallel. +* +* @param InstancePtr is the instance to work on. +* @param DestPtr is the physical destination address in flash memory +* space. +* @param SrcPtr is the source data. +* @param Bytes is the number of bytes to program. +* +* @return +* +* - XST_SUCCESS if successful. +* - XFLASH_ERROR if a write error occurred. This error is +* usually device specific. Use XFlash_DeviceControl() to +* retrieve specific error conditions. When this error is +* returned, it is possible that the target address range was +* only partially programmed. +* - XFLASH_ALIGNMENT_ERROR if the source and destination pointers +* are not aligned to a 16-bit word. +* +* @note +* +* This algorithm programs only full buffers at a time and must take care +* of the following situations: +* - Partial first buffer programming with pre and/or post padding +* required. +* - Multiple full buffer programming. +* - Partial last buffer programming with post padding. +*

+* When padding, 0xFF is written to each byte to be padded. This in effect does +* nothing to the current contents of the flash memory and saves us from having +* to merge real flash data with user data on partial buffer writes. +*

+* If hardware is failing, then this routine could get stuck in an endless loop. +* +******************************************************************************/ +static int WriteBuffer64(XFlash *InstancePtr, void *DestPtr, + void *SrcPtr, u32 Bytes) +{ + XFlashVendorData_Intel *DevDataPtr; + u32 *SrcWordPtr = (u32*)SrcPtr; + u32 *DestWordPtr = (u32*)DestPtr; + Xuint64 StatusReg; + u32 BaseAddress; + u32 ReadyMask; + u32 BytesLeft = Bytes; + u32 PartialBytes; + u32 Count; + int Status = XST_SUCCESS; + int Index; + + DevDataPtr = GET_PARTDATA(InstancePtr); + BaseAddress = InstancePtr->Geometry.BaseAddress; + ReadyMask = DevDataPtr->SR_WsmReady.Mask32; + + XUINT64_MSW(StatusReg) = 0; + XUINT64_LSW(StatusReg) = 0; + + /* + * Make sure DestPtr and SrcPtr are aligned to a 32-bit word. + */ + if (((int) SrcWordPtr & 3) || ((int) DestWordPtr & 3)) { + return (XFLASH_ALIGNMENT_ERROR); + } + + /* + * Determine if a partial first buffer must be programmed. + */ + PartialBytes = (u32) DestWordPtr & + InstancePtr->Properties.ProgCap.WriteBufferAlignmentMask; + + /* + * This write cycle programs the first partial write buffer. + */ + if (PartialBytes) { + /* + * Backup DestWord to the beginning of a buffer alignment area + * Count is the number of write cycles left after pre-filling + * the write buffer with 0xFFFF. + */ + DestWordPtr = (u32*)((u32) DestWordPtr - PartialBytes); + Count = InstancePtr->Properties.ProgCap.WriteBufferSize >> 2; + + /* + * Send command to write buffer. Wait for buffer to become + * available. + * Write number of words to be written (always the maximum) + */ + WRITE_FLASH_64x2(DestWordPtr, + InstancePtr->Command.WriteBufferCommand, + InstancePtr->Command.WriteBufferCommand); + READ_FLASH_64(DestWordPtr, StatusReg); + while (((XUINT64_MSW(StatusReg) & ReadyMask) != ReadyMask) || + ((XUINT64_LSW(StatusReg) & ReadyMask) != ReadyMask)) { + READ_FLASH_64(DestWordPtr, StatusReg); + } + WRITE_FLASH_64x2(DestWordPtr, DevDataPtr->WriteBufferWordCount, + DevDataPtr->WriteBufferWordCount); + + /* + * Write 0xFFFFFFFF padding until we get to the start of the + * user data + */ + while (PartialBytes > 3) { + WRITE_FLASH_32(DestWordPtr++, 0xFFFFFFFF); + PartialBytes -= 4; + Count--; + } + + /* + * Write the remainder of this write buffer + */ + Index = 0; + while (Count--) { + /* Full word */ + if (BytesLeft > 3) { + WRITE_FLASH_32(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 4; + } + + /* End of SrcWords */ + else if (BytesLeft == 0) { + WRITE_FLASH_32(&DestWordPtr[Index], 0xFFFFFFFF); + } + + /* Partial word */ + else if (BytesLeft == 1) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFFFF00 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x00FFFFFF | SrcWordPtr[Index]); + #endif + BytesLeft--; + } + else if (BytesLeft == 2) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFF0000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x0000FFFF | SrcWordPtr[Index]); + #endif + BytesLeft -= 2; + } + else { /* BytesLeft == 3 */ + + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFF000000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x000000FF | SrcWordPtr[Index]); + #endif + BytesLeft -= 3; + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_64x2((u32) DestWordPtr & ~7, + XFL_INTEL_CMD_CONFIRM, XFL_INTEL_CMD_CONFIRM); + Status = PollSR64(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination to last access position + */ + SrcWordPtr += Index; + DestWordPtr += Index; + } + + /* + * At this point DestPtr and SrcPtr are aligned to a write buffer + * boundary. + * The next batch of writes utilize a write cycle full of SrcData + */ + Count = InstancePtr->Properties.ProgCap.WriteBufferSize >> 2; + while (BytesLeft >= InstancePtr->Properties.ProgCap.WriteBufferSize) { + + /* + * Send command to write buffer. Wait for buffer to become + * available. + * Write number of words to be written (always the maximum) + */ + WRITE_FLASH_64x2(DestWordPtr, + InstancePtr->Command.WriteBufferCommand, + InstancePtr->Command.WriteBufferCommand); + + READ_FLASH_64(DestWordPtr, StatusReg); + while (((XUINT64_MSW(StatusReg) & ReadyMask) != ReadyMask) || + ((XUINT64_LSW(StatusReg) & ReadyMask) != ReadyMask)) { + READ_FLASH_64(DestWordPtr, StatusReg); + } + WRITE_FLASH_64x2(DestWordPtr, DevDataPtr->WriteBufferWordCount, + DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer. + */ + for (Index = 0; Index < Count; Index++) { + WRITE_FLASH_32(&DestWordPtr[Index], SrcWordPtr[Index]); + BytesLeft -= 4; + } + + /* + * Send confirmation and wait for status. + */ + WRITE_FLASH_64x2((u32) DestWordPtr & ~7, + XFL_INTEL_CMD_CONFIRM, XFL_INTEL_CMD_CONFIRM); + Status = PollSR64(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + + /* + * Increment source and destination. + */ + SrcWordPtr += Count; + DestWordPtr += Count; + } + + /* + * The last phase is to write a partial last write buffer. + */ + if (BytesLeft) { + /* + * Send command to write buffer. Wait for buffer to become + * available. + * Write number of words to be written (always the maximum). + */ + WRITE_FLASH_64x2(DestWordPtr, + InstancePtr->Command.WriteBufferCommand, + InstancePtr->Command.WriteBufferCommand); + + while (((XUINT64_MSW(StatusReg) & ReadyMask) != ReadyMask) || + ((XUINT64_LSW(StatusReg) & ReadyMask) != ReadyMask)) { + READ_FLASH_64(DestWordPtr, StatusReg); + } + WRITE_FLASH_64x2(DestWordPtr, DevDataPtr->WriteBufferWordCount, + DevDataPtr->WriteBufferWordCount); + + /* + * Fill the buffer. + */ + Index = 0; + while (Count--) { + /* + * Full word. + */ + if (BytesLeft > 3) { + WRITE_FLASH_32(&DestWordPtr[Index], + SrcWordPtr[Index]); + BytesLeft -= 4; + } + + /* End of SrcWords. */ + else if (BytesLeft == 0) { + WRITE_FLASH_32(&DestWordPtr[Index], 0xFFFFFFFF); + } + + /* Partial word. */ + else if (BytesLeft == 1) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFFFF00 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x00FFFFFF | SrcWordPtr[Index]); + #endif + BytesLeft--; + } + else if (BytesLeft == 2) { + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFFFF0000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x0000FFFF | SrcWordPtr[Index]); + #endif + BytesLeft -= 2; + } + else { /* BytesLeft == 3. */ + + #ifdef XPAR_AXI_EMC + WRITE_FLASH_32(&DestWordPtr[Index], + 0xFF000000 | SrcWordPtr[Index]); + #else + WRITE_FLASH_32(&DestWordPtr[Index], + 0x000000FF | SrcWordPtr[Index]); + #endif + BytesLeft -= 3; + } + Index++; + } + + /* + * Buffer write completed. Send confirmation command and wait + * for completion. + */ + WRITE_FLASH_64x2((u32) DestWordPtr & ~7, + XFL_INTEL_CMD_CONFIRM, XFL_INTEL_CMD_CONFIRM); + Status = PollSR64(InstancePtr, + ((u32)DestWordPtr) - BaseAddress); + if (Status != XFLASH_READY) { + return (Status); + } + } + + return (XST_SUCCESS); +} + + +/*****************************************************************************/ +/** +* +* Reads and interprets part identification data. +* +* @param InstancePtr is the instance to work on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void GetPartID(XFlash *InstancePtr) +{ + XFlashVendorData_Intel *DevDataPtr; + u32 CmdAddress; + void *Ptr; + u8 Interleave; + u8 Mode; + + DevDataPtr = GET_PARTDATA(InstancePtr); + CmdAddress = InstancePtr->Geometry.BaseAddress; + Interleave = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_CFI_INTERL_MASK) >> 24; + Mode = (InstancePtr->Geometry.MemoryLayout & + XFL_LAYOUT_PART_MODE_MASK) >> 8; + + /* + * Send Read id codes command. + */ + DevDataPtr->SendCmd(CmdAddress, 8, + XFL_INTEL_CMD_READ_ID_CODES); + + /* + * Retrieve Manufacturer ID located at word offset 0. + */ + XFL_CFI_POSITION_PTR(Ptr, CmdAddress, Interleave, 0); + InstancePtr->Properties.PartID.ManufacturerID = + XFlashCFI_Read8((u8*)Ptr, Interleave, Mode); + + /* + * Retrieve Device Code located at word offset 1. + */ + XFL_CFI_ADVANCE_PTR8(Ptr, Interleave); + InstancePtr->Properties.PartID.DeviceID = + XFlashCFI_Read8((u8*)Ptr, Interleave, Mode); + + /* + * Place device(s) back into read-array mode. + */ + (void) XFlashIntel_Reset(InstancePtr); +} + +/*****************************************************************************/ +/** +* +* Sets the RYBY control signal. +* +* @param InstancePtr is the instance to work on. +* @param Mode is the mode to set the RYBY signal to. +* +* @return +* +* - XST_SUCCESS if the mode was successfully +* changed. +* - XFLASH_NOT_SUPPORTED if the mode given is +* unknown/unsupported. +* +* @note None. +* +******************************************************************************/ +static int SetRYBY(XFlash *InstancePtr, u32 Mode) +{ + u32 Cmd; + XFlashVendorData_Intel *DevDataPtr; + + /* + * Determine which command code to use. + */ + switch (Mode) { + case XFL_INTEL_RYBY_PULSE_OFF: + Cmd = XFL_INTEL_CONFIG_RYBY_LEVEL; + break; + + case XFL_INTEL_RYBY_PULSE_ON_ERASE: + Cmd = XFL_INTEL_CONFIG_RYBY_PULSE_ERASE; + break; + + case XFL_INTEL_RYBY_PULSE_ON_PROG: + Cmd = XFL_INTEL_CONFIG_RYBY_PULSE_WRITE; + break; + + case XFL_INTEL_RYBY_PULSE_ON_ERASE_PROG: + Cmd = XFL_INTEL_CONFIG_RYBY_PULSE_ALL; + break; + + default: + return (XFLASH_NOT_SUPPORTED); + } + + /* + * Send the command to the devices. + */ + DevDataPtr = GET_PARTDATA(InstancePtr); + DevDataPtr->SendCmdSeq(InstancePtr->Geometry.BaseAddress, 0, + XFL_INTEL_CMD_CONFIG, Cmd); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* Sends commands to erase blocks. +* +* @param InstancePtr is the pointer to xflash object to work on. +* @param Region is the region which the first block appears. +* @param Block is the starting block to erase. +* @param MaxBlocks is the number of consecutive blocks to erase. +* +* @return The number of blocks enqueued to the part's erase buffer. +* Region and Block parameters are incremented the number of blocks +* queued. +* +* @note Limitation: Only support enqueuing one block at a time. +* +******************************************************************************/ +static u16 EnqueueEraseBlocks(XFlash *InstancePtr, u16 *Region, + u16 *Block, u16 MaxBlocks) +{ + XFlashGeometry *GeomPtr; + XFlashVendorData_Intel *DevDataPtr; + u32 BlockAddress; + + /* + * If for some reason the maximum number of blocks to enqueue is + * zero, then don't do anything. + */ + if (MaxBlocks == 0) { + return (0); + } + + GeomPtr = &InstancePtr->Geometry; + DevDataPtr = GET_PARTDATA(InstancePtr); + + /* + * Get the physical address to write the command to and send command. + */ + (void) XFlashGeometry_ToAbsolute(GeomPtr, *Region, *Block, 0, + &BlockAddress); + DevDataPtr->SendCmdSeq(GeomPtr->BaseAddress, BlockAddress, + XFL_INTEL_CMD_BLOCK_ERASE, + XFL_INTEL_CMD_CONFIRM); + + /* + * Increment Region/Block. + */ + XFL_GEOMETRY_INCREMENT(GeomPtr, *Region, *Block); + + /* + * Return the number of blocks enqueued. + */ + return (1); +} + +#endif /* XPAR_XFL_DEVICE_FAMILY_INTEL */