embeddedsw/lib/sw_services/xilisf/src/xilisf_write.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

957 lines
30 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_write.c
*
* This file contains the library functions to write to the Serial Flash
* devices. Refer xilisf.h for 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.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
* Added support to SST flash on SPI PS interface.
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
* interface.
* Changed API:
* WriteData()
* XIsf_Write()
* </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 WriteData(XIsf *InstancePtr, u8 Command, u32 Address,
const u8 *BufferPtr, u32 ByteCount);
static int AutoPageWrite(XIsf *InstancePtr, u32 Address);
static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr,
u32 ByteOffset, u32 NumBytes);
static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address);
static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address);
static int WriteSR(XIsf *InstancePtr, u8 SRData);
static int WriteSR2(XIsf *InstancePtr, u8 *SRData);
static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr);
/************************** Variable Definitions *****************************/
extern u32 XIsf_StatusEventInfo;
extern unsigned int XIsf_ByteCountInfo;
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* This API writes the data to the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Operation is the type of write operation to be performed on the
* Serial Flash.
* The different operations are
* - XISF_WRITE: Normal Write
* - XISF_DUAL_IP_PAGE_WRITE: Dual Input Fast Program
* - XISF_DUAL_IP_EXT_PAGE_WRITE: Dual Input Extended Fast Program
* - XISF_QUAD_IP_PAGE_WRITE: Quad Input Fast Program
* - XISF_QUAD_IP_EXT_PAGE_WRITE: Quad Input Extended Fast Program
* - XISF_AUTO_PAGE_WRITE: Auto Page Write
* - XISF_BUFFER_WRITE: Buffer Write
* - XISF_BUF_TO_PAGE_WRITE_WITH_ERASE: Buffer to Page Transfer
* with Erase
* - XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE: Buffer to Page Transfer
* without Erase
* - XISF_WRITE_STATUS_REG: Status Register Write
* - XISF_WRITE_STATUS_REG2: 2 byte Status Register Write
* - XISF_OTP_WRITE: OTP Write.
*
* @param OpParamPtr is pointer to a structure variable which contains
* operational parameters of the specified operation.
* This parameter type is dependant on value of first argument
* (Operation).
*
* - Normal Write (XISF_WRITE), Dual Input Fast Program
* (XISF_DUAL_IP_PAGE_WRITE), Dual Input Extended Fast Program
* (XISF_DUAL_IP_EXT_PAGE_WRITE), Quad Input Fast Program
* (XISF_QUAD_IP_PAGE_WRITE), Quad Input Extended Fast Program
* (XISF_QUAD_IP_EXT_PAGE_WRITE):
* The OpParamPtr must be of type struct XIsf_WriteParam.
* OpParamPtr->Address is the start address in the Serial Flash.
* OpParamPtr->WritePtr is a pointer to the data to be written to
* the Serial Flash.
* OpParamPtr->NumBytes is the number of bytes to be written to
* Serial Flash.
* This operation is supported for Atmel, Intel, STM, Winbond and
* Spansion Serial Flash.
*
* - Auto Page Write (XISF_AUTO_PAGE_WRITE):
* The OpParamPtr must be of 32 bit unsigned integer variable.
* This is the address of page number in the Serial Flash which is
* to be refreshed.
* This operation is only supported for Atmel Serial Flash.
*
* - Buffer Write (XISF_BUFFER_WRITE):
* The OpParamPtr must be of type struct
* XIsf_BufferToFlashWriteParam.
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the
* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* AT45DB011D Flash as it contains a single buffer.
* OpParamPtr->WritePtr is a pointer to the data to be written to
* the Serial Flash SRAM Buffer.
* OpParamPtr->ByteOffset is byte offset in the buffer from where
* the data is to be written.
* OpParamPtr->NumBytes is number of bytes to be written to the
* Buffer.
* This operation is supported only for Atmel Serial Flash.
*
* - Buffer To Memory Write With Erase
* (XISF_BUF_TO_PAGE_WRITE_WITH_ERASE)/
* Buffer To Memory Write Without Erase
* (XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE):
* The OpParamPtr must be of type struct
* XIsf_BufferToFlashWriteParam.
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the
* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* AT45DB011D Flash as it contains a single buffer.
* OpParamPtr->Address is starting address in the Serial Flash
* memory from where the data is to be written.
* These operations are only supported for Atmel Serial Flash.
*
* - Write Status Register (XISF_WRITE_STATUS_REG):
* The OpParamPtr must be of type of 8 bit unsigned integer
* variable. This is the value to be written to the Status
* Register.
* This operation is only supported for Intel, STM Winbond and
* Spansion Serial Flash.
*
* - Write Status Register2 (XISF_WRITE_STATUS_REG2):
* The OpParamPtr must be of type (u8 *) and should point to two
* 8 bit unsigned integer values. This is the value to be written
* to the 16 bit Status Register.
* This operation is only supported in Winbond (W25Q) Serial Flash.
*
* - One Time Programmable Area Write (XISF_OTP_WRITE):
* The OpParamPtr must be of type struct XIsf_WriteParam.
* OpParamPtr->Address is the address in the SRAM Buffer of the
* Serial Flash to which the data is to be written.
* OpParamPtr->WritePtr is a pointer to the data to be written to
* the Serial Flash.
* OpParamPtr->NumBytes should be set to 1 when performing
* OTPWrite operation.
* This operation is only supported for Intel Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - Application must fill the structure elements of the third
* argument and pass its pointer by type casting it with void
* pointer.
* - For Intel, STM, Winbond and Spansion Serial Flash, the user
* application must call the XIsf_WriteEnable() API by passing
* XISF_WRITE_ENABLE as an argument, before calling the
* XIsf_Write() API.
*
******************************************************************************/
int XIsf_Write(XIsf *InstancePtr, XIsf_WriteOperation Operation,
void *OpParamPtr)
{
int Status = (int)XST_FAILURE;
u8 Mode;
XIsf_WriteParam *WriteParamPtr;
XIsf_BufferWriteParam *BufferWriteParamPtr;
XIsf_BufferToFlashWriteParam *BufferToFlashWriteParamPtr;
if (InstancePtr == NULL) {
return (int)XST_FAILURE;
}
if (InstancePtr->IsReady != TRUE) {
return (int)XST_FAILURE;
}
if (NULL == OpParamPtr) {
return (int)XST_FAILURE;
}
switch (Operation) {
case XISF_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_PAGEPROG_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
case XISF_AUTO_PAGE_WRITE:
Status = AutoPageWrite(InstancePtr,
*((u32*)(void *) OpParamPtr));
break;
case XISF_BUFFER_WRITE:
BufferWriteParamPtr = (XIsf_BufferWriteParam*)
(void *) OpParamPtr;
Xil_AssertNonvoid(BufferWriteParamPtr != NULL);
Status = BufferWrite(InstancePtr,
BufferWriteParamPtr->BufferNum,
BufferWriteParamPtr->WritePtr,
BufferWriteParamPtr->ByteOffset,
BufferWriteParamPtr->NumBytes);
break;
case XISF_BUF_TO_PAGE_WRITE_WITH_ERASE:
BufferToFlashWriteParamPtr =
(XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL);
Status = BufferToFlashWriteWithErase(InstancePtr,
BufferToFlashWriteParamPtr->BufferNum,
BufferToFlashWriteParamPtr->Address);
break;
case XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE:
BufferToFlashWriteParamPtr =
(XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL);
Status = BufferToFlashWriteWithoutErase(InstancePtr,
BufferToFlashWriteParamPtr->BufferNum,
BufferToFlashWriteParamPtr->Address);
break;
case XISF_WRITE_STATUS_REG:
Status = WriteSR(InstancePtr,
*((u8*)(void *) OpParamPtr));
break;
case XISF_OTP_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
if (1 == WriteParamPtr->NumBytes) {
Status = WriteOTPData(InstancePtr,
WriteParamPtr->Address,
WriteParamPtr->WritePtr);
}
break;
case XISF_WRITE_STATUS_REG2:
Status = WriteSR2(InstancePtr,
(u8*)(void *) OpParamPtr);
break;
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
case XISF_QUAD_IP_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_QUAD_IP_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) ||
(XPAR_XISF_FLASH_FAMILY == STM) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION))*/
#if (XPAR_XISF_FLASH_FAMILY == STM)
case XISF_DUAL_IP_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_DUAL_IP_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
case XISF_DUAL_IP_EXT_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_DUAL_IP_EXT_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
case XISF_QUAD_IP_EXT_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_QUAD_IP_EXT_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
#endif /* (XPAR_XISF_FLASH_FAMILY == STM) */
default:
break;
}
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
if(Mode == XISF_INTERRUPT_MODE){
InstancePtr->StatusHandler(InstancePtr,
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
}
return Status;
}
/*****************************************************************************/
/**
*
* This function writes the data to the specified address locations in Serial
* Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address in the Serial Flash memory, where the
* data is to be written.
* @param BufferPtr is a pointer to the data to be written to Serial
* Flash.
* @param ByteCount is the number of bytes to be written.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one byte and a maximum of one Page can be
* written using this function.
* - This operation is supported for Atmel, Intel, STM, Winbond
* and Spansion Serial Flash.
*
******************************************************************************/
static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address,
const u8 *BufferPtr, u32 ByteCount)
{
u8 Mode;
u32 Index;
u32 BankSel;
u32 RealAddr;
int Status;
u8 FlagStatus[2] = {0};
u8 FlashStatus[2] = {0};
u8 * NULLPtr = NULL;
const u8 * LocalBufPtr = BufferPtr;
#ifdef XPAR_XISF_INTERFACE_PSQSPI
u32 FlashMake = InstancePtr->ManufacturerID;
#endif
u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 };
u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0};
if ((ByteCount <= 0) || (ByteCount > InstancePtr->BytesPerPage)) {
return (int)XST_FAILURE;
}
if (LocalBufPtr == NULL) {
return (int)XST_FAILURE;
}
/*
* Translate address based on type of connection
* If stacked assert the slave select based on address
*/
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* 0x18 is the DeviceIDMemSize for different make of
* flashes of size 16MB
*/
if(InstancePtr->DeviceIDMemSize > 0x18) {
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
/*
* Seting the transfer mode to Polled Mode before
* performing the Bank Select operation.
*/
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
/*
* Calculate bank
*/
BankSel = RealAddr/SIXTEENMB;
/*
* Select bank
*/
(void)SendBankSelect(InstancePtr, BankSel);
/*
* Restoring the transfer mode back
*/
XIsf_SetTransferMode(InstancePtr, Mode);
}
#endif
InstancePtr->WriteBufPtr[BYTE1] = Command;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr);
for(Index = 4U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES);
Index++) {
InstancePtr->WriteBufPtr[Index] = *LocalBufPtr;
LocalBufPtr += 1;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
#endif
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
(ByteCount + XISF_CMD_SEND_EXTRA_BYTES));
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
if((InstancePtr->NumDie > 1) &&
(FlashMake == XISF_MANUFACTURER_ID_MICRON)) {
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
if(Status != (int)XST_SUCCESS){
return (int)XST_FAILURE;
}
}
/*
* Wait for the write command to the Flash to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the Flash to determine when it
* completes, by sending a read status command and receiving
* status byte
*/
Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf,
FlashStatus, (u32)sizeof(ReadStatusCmdBuf));
if(Status != (int)XST_SUCCESS){
return (int)XST_FAILURE;
}
/*
* If status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
if((InstancePtr->NumDie > 1) &&
(FlashMake == XISF_MANUFACTURER_ID_MICRON)) {
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
if(Status != (int)XST_SUCCESS){
return (int)XST_FAILURE;
}
}
#endif
return Status;
}
/*****************************************************************************/
/**
*
* This function Auto rewrites the contents of a Page in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of the page to be refreshed.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int AutoPageWrite(XIsf *InstancePtr, u32 Address)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_AUTOPAGE_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data to the specified SRAM buffer of the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer of the Serial
* Flash. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* Atmel AT45DB011D Serial Flash as it contains a single buffer.
* @param WritePtr is the pointer to the data to be written to the
* Serial Flash SRAM Buffer.
* @param ByteOffset is the byte offset in the buffer from where the
* data is to be written.
* @param NumBytes is the number of bytes to be written to the Buffer.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one byte and a maximum of one SRAM buffer can be
* written using this function.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr,
u32 ByteOffset, u32 NumBytes)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(WritePtr != NULL);
Xil_AssertNonvoid(ByteOffset != 0);
Xil_AssertNonvoid(NumBytes != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
u16 Index;
/*
* Check buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(BufferNum != XISF_PAGE_BUFFER1)) {
return (int)XST_FAILURE;
}
}
else{
return (int)XST_FAILURE;
}
if (WritePtr == NULL) {
return (int)XST_FAILURE;
}
if (ByteOffset > InstancePtr->BytesPerPage) {
return (int)XST_FAILURE;
}
if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) {
return (int)XST_FAILURE;
}
if (BufferNum == XISF_PAGE_BUFFER1) {
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER1_WRITE;
}
else{
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER2_WRITE;
}
InstancePtr->WriteBufPtr[BYTE2] = (u8) (0x00);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) ByteOffset;
for(Index = 4; Index < NumBytes + XISF_CMD_SEND_EXTRA_BYTES; Index++) {
InstancePtr->WriteBufPtr[Index] = *WritePtr++;
}
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
(NumBytes + XISF_CMD_SEND_EXTRA_BYTES));
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function first erases a page and then writes data from the specified
* internal SRAM buffer to the specified locations in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer, from which the
* data needs to be written to the Serial Flash. The valid values
* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2
* is not valid in the case of Atmel AT45DB011D Serial Flash as it
* contains a single buffer.
* @param Address is the starting address in the Serial Flash where
* the data has to be written. Byte address in this address is
* ignored as an entire Page is transferred using this API.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one Page and a maximum of one Page can be
* written using this function.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Check whether the buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(BufferNum != XISF_PAGE_BUFFER1)) {
return (int)XST_FAILURE;
}
}
else {
return (int)XST_FAILURE;
}
if (BufferNum == XISF_PAGE_BUFFER1) {
/*
* Buffer 1 to Page Program With Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] =
XISF_CMD_ERASE_BUF1TOPAGE_WRITE;
} else {
/*
* Buffer 2 to Page Program With Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] =
XISF_CMD_ERASE_BUF2TOPAGE_WRITE;
}
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data from the specified internal SRAM buffer to the
* specified locations in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer, from which the
* data needs to be written to the Serial Flash. The valid values
* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2
* is not valid in the case of Atmel AT45DB011D Serial Flash as it
* contains a single buffer.
* @param Address is the starting address in the Serial Flash where
* data has to be written. Byte address in this address will be
* ignored as an entire page of data is transferred using this
* operation.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* - A minimum of one Page and a maximum of one Page can be
* written using this function.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Check whether the buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(XISF_PAGE_BUFFER1 != 1)) {
return (int)XST_FAILURE;
}
}
else {
return (int)XST_FAILURE;
}
if (BufferNum == XISF_PAGE_BUFFER1) {
/*
* Buffer 1 to Page Program Without Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF1TOPAGE_WRITE;
}
else {
/*
* Buffer 2 to Page Program Without Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF2TOPAGE_WRITE;
}
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data to the Status Register of the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param SRData is the value to be written to the Status Register
* of the Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported in Intel, STM, Winbond and
* Spansion Serial Flash. This is the write of Status Register 1
* for Winbond devices, write of Status Register 2 is handled by
* WriteSR2.
*
******************************************************************************/
static int WriteSR(XIsf *InstancePtr, u8 SRData)
{
int Status = XST_FAILURE;
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
(XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST))
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = SRData;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_STATUS_RDWR_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \\
(XPAR_XISF_FLASH_FAMILY == WINBOND) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data to Status Register of the Serial Flash. This API
* should be used to write to the 16 bit status register in Winbond Quad Flash
* (W25QXX).
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param SRData is of type (u8*) and points to the 16 bit value to be
* written to the Status Register of the Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported in Winbond (W25QXX) Serial
* Flash.
*
******************************************************************************/
static int WriteSR2(XIsf *InstancePtr, u8 *SRData)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(SRData != NULL);
#if (XPAR_XISF_FLASH_FAMILY == WINBOND)
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = *SRData++;
InstancePtr->WriteBufPtr[BYTE3] = *SRData;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_STATUS_RDWR_BYTES + 1);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes one byte of data to the OTP area in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address in the OTP area, where to write data.
* @param BufferPtr is the pointer to the data to be written into OTP
* region of Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one byte and a maximum of one byte can be
* written using this function.
* - This operation is supported only for Intel Serial Flash.
*
******************************************************************************/
static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
Xil_AssertNonvoid(BufferPtr != NULL);
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
if (BufferPtr == NULL) {
return (int)XST_FAILURE;
}
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_OTP_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) Address;
InstancePtr->WriteBufPtr[BYTE5] = *BufferPtr;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_OTP_RDWR_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
return Status;
}