/****************************************************************************** * * 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. * *
* * 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() ** ******************************************************************************/ /***************************** 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; }