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
+* 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
+* 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
+* 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
+* 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
+* 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. +*
+* 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. +*
+* +* 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. +*