embeddedsw/lib/sw_services/xilflash/src/xilflash.c
Jagannadha Sutradharudu Teki 2c8f92039d embeddesw: Add initial code support
Added initial support Xilinx Embedded Software.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
2014-06-24 16:45:01 +05:30

682 lines
22 KiB
C
Executable file

/******************************************************************************
*
* 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 THE
* XILINX CONSORTIUM 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
*
* <pre>
* 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.
* </pre>
*
*
****************************************************************************/
/***************************** 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);
}