embeddedsw/lib/sw_services/xilisf/src/xilisf_erase.c
Shakti Bhatnagar c2b6e79695 xiliisf: Updated xilisf lib
Updated the lib src files as well as the examples
for the major version change v5_0

Signed-off-by: Shakti Bhatnagar <shaktib@xilinx.com>
2014-09-02 11:21:18 +05:30

583 lines
17 KiB
C
Executable file

/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 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 xilisf_erase.c
*
* This file contains the library functions to Erase the Serial Flash.
* Refer xilisf.h for a detailed description.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------
* 1.00a ksu/sdm 03/03/08 First release
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
* flash memories
* 3.02a srt 04/25/13 Added Bulk Erase command support for SST and
* Spansion flashes.
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
* interface.
* New API:
* DieErase()
* Changed API:
* SectorErase()
* BulkErase()
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "include/xilisf.h"
/************************** Constant Definitions *****************************/
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
u32 ByteCount);
extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
#endif
static int PageErase(XIsf *InstancePtr, u32 Address);
static int BlockErase(XIsf *InstancePtr, u32 Address);
static int SectorErase(XIsf *InstancePtr, u32 Address);
static int BulkErase(XIsf *InstancePtr);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
static int DieErase(XIsf *InstancePtr);
#endif
/************************** Variable Definitions *****************************/
extern u32 XIsf_StatusEventInfo;
extern unsigned int XIsf_ByteCountInfo;
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* This API erases the contents of the specified memory in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Operation is the type of Erase operation to be performed on the
* Serial Flash.
* The different operations are
* - XISF_PAGE_ERASE: Page Erase
* - XISF_BLOCK_ERASE: Block Erase
* - XISF_SECTOR_ERASE: Sector Erase
- XISF_BULK_ERASE: Bulk Erase
* @param Address is the address of the Page/Block/Sector to be erased.
* The address can be either Page address, Block address or Sector
* address based on the Erase operation to be performed.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - For Intel, STM, Winbond or Spansion Serial Flash the user
* application must call XIsf_WriteEnable() API by passing
* XISF_WRITE_ENABLE as an argument before calling XIsf_Erase()
* API.
* - Atmel Serial Flash support Page/Block/Sector Erase
- operations.
* - Intel, Winbond, Numonyx (N25QXX) and Spansion Serial Flash
* support Sector/Block/Bulk Erase operations.
* - STM (M25PXX) Serial Flash support Sector/Bulk Erase
* operations.
*
******************************************************************************/
int XIsf_Erase(XIsf *InstancePtr, XIsf_EraseOperation Operation, u32 Address)
{
int Status = (int)(XST_FAILURE);
u8 Mode;
if (InstancePtr == NULL) {
return (int)(XST_FAILURE);
}
if (InstancePtr->IsReady != TRUE) {
return (int)(XST_FAILURE);
}
switch (Operation) {
case XISF_PAGE_ERASE:
Status = PageErase(InstancePtr, Address);
break;
case XISF_BLOCK_ERASE:
Status = BlockErase(InstancePtr, Address);
break;
case XISF_SECTOR_ERASE:
Status = SectorErase(InstancePtr, Address);
break;
case XISF_BULK_ERASE:
Status = BulkErase(InstancePtr);
break;
default:
break;
}
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
if(Mode == XISF_INTERRUPT_MODE){
InstancePtr->StatusHandler(InstancePtr,
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
}
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Page in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of Page to be erased. This can be any
* address in the Page to be erased. The Byte address values in
* this address are ignored.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int PageErase(XIsf *InstancePtr, u32 Address)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PAGE_ERASE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULL, XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Block in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of the Block to be erased. This can be
* any address in the Block to be erased. The Page/Byte address
* values in this address are ignored.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is supported for Atmel, Intel, Winbond,
* Numonyx (N25QXX), and Spansion Serial Flash.
*
******************************************************************************/
static int BlockErase(XIsf *InstancePtr, u32 Address)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == INTEL) \
|| (XPAR_XISF_FLASH_FAMILY == WINBOND))
#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == WINBOND))
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BLOCK_ERASE;
#else
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PARAM_BLOCK_ERASE;
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULL, XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* ((XPAR_XISF_FLASH_FAMILY==ATMEL)||(XPAR_XISF_FLASH_FAMILY==INTEL)) */
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Sector in Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of the Sector to be erased. This can be
* any address in the Sector to be erased.
* The Block/Page/Byte address values in this address are ignored.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is supported for Atmel, Intel, STM, Winbond
* and Spansion Serial Flash.
*
******************************************************************************/
static int SectorErase(XIsf *InstancePtr, u32 Address)
{
int Status = (int)(XST_FAILURE);
u8 Mode;
u32 BankSel;
u32 RealAddr;
u8* NULLPtr = NULL;
u8 FlagStatus[2] = {0};
u8 FlashStatus[2] = {0};
u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 };
u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0};
#ifdef XPAR_XISF_INTERFACE_PSQSPI
u32 FlashMake = InstancePtr->ManufacturerID;
#endif
/*
* Translate address based on type of connection
* If stacked assert the slave select based on address
*/
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* Initial bank selection
*/
if(InstancePtr->DeviceIDMemSize > 0x18U) {
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
/*
* Seting the transfer mode to Polled Mode before
* performing the Bank Select operation.
*/
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
/*
* Calculate initial bank
*/
BankSel = RealAddr/SIXTEENMB;
/*
* Select bank
*/
Status = SendBankSelect(InstancePtr, BankSel);
/*
* Restoring the transfer mode back
*/
XIsf_SetTransferMode(InstancePtr, Mode);
if(Status!=(int)(XST_SUCCESS)){
return (int)XST_FAILURE;
}
}
#endif
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif
Xil_AssertNonvoid(NULLPtr == NULL);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULLPtr, XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
if((InstancePtr->NumDie > (u8)1) &&
(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
}
/*
* Wait for the sector erase command to the Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf,
FlashStatus,
(u32)sizeof(ReadStatusCmdBuf));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
if((InstancePtr->NumDie > (u8)1) &&
(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
Status =
XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
}
#endif
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the content of an entire Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is supported for Intel, STM, Winbond,
* Spansion and SST Serial Flashes.
*
******************************************************************************/
static int BulkErase(XIsf *InstancePtr)
{
int Status = (int)(XST_FAILURE);
u8* NULLPtr = NULL;
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
(XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST) \
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* If the number of die is greater than 1 call die erase
*/
if(InstancePtr->NumDie > 1){
Status = DieErase(InstancePtr);
}
else{
#endif
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BULK_ERASE;
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
Xil_AssertNonvoid(NULLPtr == NULL);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULLPtr, XISF_BULK_ERASE_BYTES);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
}
#endif
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY==STM)) \
(XPAR_XISF_FLASH_FAMILY == WINBOND) ||
(XPAR_XISF_FLASH_FAMILY == SST) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
return Status;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*****************************************************************************/
/**
*
* This function erases the content of a Die of Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is supported for Winbond,
* Spansion and Micron Serial Flashes.
*
******************************************************************************/
static int DieErase(XIsf *InstancePtr)
{
int Status = (int)(XST_FAILURE);
u8* NULLPtr = NULL;
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
(XPAR_XISF_FLASH_FAMILY == SPANSION))
u8 DieCnt;
u8 ReadFlagSRCmd[] = { READ_FLAG_STATUS_CMD, 0 };
u8 FlagStatus[2] = {0};
for(DieCnt = 0; DieCnt < InstancePtr->NumDie; DieCnt++) {
/*
* Select bank - the lower of the 2 banks in each die
* This is specific to Micron flash
*/
Status = SendBankSelect(InstancePtr, DieCnt*2);
/*
* Setup the write command with the specified address and data
* for the Flash
*/
/*
* This ensures 3B address is sent to flash even with address
* greater than 128Mb.
* The address is the start address of die - MSB bits will be
* derived from bank select by the flash
*/
InstancePtr->WriteBufPtr[BYTE1] = DIE_ERASE_CMD;
InstancePtr->WriteBufPtr[BYTE2] = 0x00;
InstancePtr->WriteBufPtr[BYTE3] = 0x00;
InstancePtr->WriteBufPtr[BYTE4] = 0x00;
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
Xil_AssertNonvoid(NULLPtr == NULL);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
Status =
XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
DIE_ERASE_SIZE);
/*
* Wait for the sector erase command to Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
Status =
XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlagStatus[1] & (u8)0x80) == (u8)0x80) {
break;
}
}
}
#endif /* ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
return Status;
}
#endif