
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>
939 lines
29 KiB
C
Executable file
939 lines
29 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_read.c
|
|
*
|
|
* This file contains the library functions to read data from 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
|
|
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
|
|
* interface.
|
|
* Changed API:
|
|
* ReadData()
|
|
* FastReadData()
|
|
* </pre>
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
#include "include/xilisf.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
#define FAST_READ_NUM_DUMMY_BYTES 1
|
|
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
|
|
#define BANKMASK 0xF000000 /**< Bank mask */
|
|
|
|
/**************************** 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 ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
|
|
u32 ByteCount);
|
|
static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address,
|
|
u8 *ReadPtr,
|
|
u32 ByteCount, int NumDummyBytes);
|
|
static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address);
|
|
static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
|
u32 ByteOffset, u32 NumBytes);
|
|
static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
|
u32 ByteOffset, u32 NumBytes);
|
|
static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
|
|
u32 ByteCount);
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
extern u32 XIsf_StatusEventInfo;
|
|
extern unsigned int XIsf_ByteCountInfo;
|
|
/************************** Function Definitions ******************************/
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This API reads the data from the Serial Flash.
|
|
*
|
|
* @param InstancePtr is a pointer to the XIsf instance.
|
|
* @param Operation is the type of the read operation to be performed on
|
|
* the Serial Flash.
|
|
* The different operations are
|
|
- XISF_READ: Normal Read
|
|
* - XISF_FAST_READ: Fast Read
|
|
* - XISF_PAGE_TO_BUF_TRANS: Page to Buffer Transfer
|
|
* - XISF_BUFFER_READ: Buffer Read
|
|
* - XISF_FAST_BUFFER_READ: Fast Buffer Read
|
|
* - XISF_OTP_READ: One Time Programmable Area (OTP) Read
|
|
* - XISF_DUAL_OP_FAST_READ: Dual Output Fast Read
|
|
* - XISF_DUAL_IO_FAST_READ: Dual Input/Output Fast Read
|
|
* - XISF_QUAD_OP_FAST_READ: Quad Output Fast Read
|
|
* - XISF_QUAD_IO_FAST_READ: Quad Input/Output Fast Read
|
|
* @param OpParamPtr is the pointer to structure variable which contains
|
|
* operational parameter of specified Operation. This parameter
|
|
* type is dependant on the type of Operation to be performed.
|
|
*
|
|
* - Normal Read (XISF_READ), Fast Read (XISF_FAST_READ),
|
|
* One Time Programmable Area Read(XISF_OTP_READ), Dual Output
|
|
* Fast Read (XISF_CMD_DUAL_OP_FAST_READ), Dual Input/Output
|
|
* Fast Read (XISF_CMD_DUAL_IO_FAST_READ), Quad Output Fast Read
|
|
* (XISF_CMD_QUAD_OP_FAST_READ) and Quad Input/Output Fast Read
|
|
* (XISF_CMD_QUAD_IO_FAST_READ):
|
|
* The OpParamPtr must be of type struct XIsf_ReadParam.
|
|
* OpParamPtr->Address is start address in the Serial Flash.
|
|
* OpParamPtr->ReadPtr is a pointer to the memory where the data
|
|
* read from the Serial Flash is stored.
|
|
* OpParamPtr->NumBytes is number of bytes to read.
|
|
* OpParamPtr->NumDummyBytes is the number of dummy bytes to be
|
|
* transmitted for the Read command. This parameter is only used
|
|
* in case of Dual and Quad reads.
|
|
* Normal Read and Fast Read operations are supported for Atmel,
|
|
* Intel, STM, Winbond and Spansion Serial Flash.
|
|
* Dual and quad reads are supported for Winbond (W25QXX), Numonyx
|
|
* (N25QXX) and Spansion (S25FL129) quad flash.
|
|
* OTP Read operation is only supported in Intel Serial Flash.
|
|
*
|
|
* - Page To Buffer Transfer (XISF_PAGE_TO_BUF_TRANS):
|
|
* The OpParamPtr must be of type struct
|
|
* XIsf_FlashToBufTransferParam .
|
|
* 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 start address in the Serial Flash.
|
|
* This operation is only supported in Atmel Serial Flash.
|
|
*
|
|
* - Buffer Read (XISF_BUFFER_READ) and Fast Buffer Read
|
|
* (XISF_FAST_BUFFER_READ):
|
|
* The OpParamPtr must be of type struct XIsf_BufferReadParam.
|
|
* 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->ReadPtr is pointer to the memory where data read
|
|
* from the SRAM buffer is to be stored.
|
|
* OpParamPtr->ByteOffset is byte offset in the SRAM buffer from
|
|
* where the first byte is read.
|
|
* OpParamPtr->NumBytes is the number of bytes to be read from the
|
|
* Buffer.
|
|
* These operations are supported only in Atmel 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.
|
|
* - The valid data is available from the fourth location pointed
|
|
* to by the ReadPtr for Normal Read and Buffer Read operations.
|
|
* - The valid data is available from fifth location pointed to
|
|
* by the ReadPtr for Fast Read, Fast Buffer Read and OTP Read
|
|
* operations.
|
|
* - The valid data is available from the (4 + NumDummyBytes)th
|
|
* location pointed to by ReadPtr for Dual/Quad Read operations.
|
|
*
|
|
******************************************************************************/
|
|
int XIsf_Read(XIsf *InstancePtr, XIsf_ReadOperation Operation,
|
|
void *OpParamPtr)
|
|
{
|
|
int Status = (int)(XST_FAILURE);
|
|
u8 Mode;
|
|
XIsf_ReadParam *ReadParamPtr;
|
|
XIsf_FlashToBufTransferParam *FlashToBufTransferParamPtr;
|
|
XIsf_BufferReadParam *BufferReadParamPtr;
|
|
|
|
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_READ:
|
|
ReadParamPtr = (XIsf_ReadParam*) OpParamPtr;
|
|
Status = ReadData(InstancePtr,
|
|
ReadParamPtr->Address,
|
|
ReadParamPtr->ReadPtr,
|
|
ReadParamPtr->NumBytes);
|
|
break;
|
|
|
|
case XISF_FAST_READ:
|
|
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
|
Status = FastReadData(InstancePtr,
|
|
XISF_CMD_FAST_READ,
|
|
ReadParamPtr->Address,
|
|
ReadParamPtr->ReadPtr,
|
|
ReadParamPtr->NumBytes,
|
|
ReadParamPtr->NumDummyBytes);
|
|
break;
|
|
|
|
case XISF_PAGE_TO_BUF_TRANS:
|
|
FlashToBufTransferParamPtr =
|
|
(XIsf_FlashToBufTransferParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(FlashToBufTransferParamPtr != NULL);
|
|
Status = FlashToBufTransfer(InstancePtr,
|
|
FlashToBufTransferParamPtr->BufferNum,
|
|
FlashToBufTransferParamPtr->Address);
|
|
break;
|
|
|
|
case XISF_BUFFER_READ:
|
|
BufferReadParamPtr =
|
|
(XIsf_BufferReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(BufferReadParamPtr != NULL);
|
|
Status = BufferRead(InstancePtr,
|
|
BufferReadParamPtr->BufferNum,
|
|
BufferReadParamPtr->ReadPtr,
|
|
BufferReadParamPtr->ByteOffset,
|
|
BufferReadParamPtr->NumBytes);
|
|
break;
|
|
|
|
case XISF_FAST_BUFFER_READ:
|
|
BufferReadParamPtr =
|
|
(XIsf_BufferReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(BufferReadParamPtr != NULL);
|
|
Status = FastBufferRead(InstancePtr,
|
|
BufferReadParamPtr->BufferNum,
|
|
BufferReadParamPtr->ReadPtr,
|
|
BufferReadParamPtr->ByteOffset,
|
|
BufferReadParamPtr->NumBytes);
|
|
break;
|
|
|
|
case XISF_OTP_READ:
|
|
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
|
Status = ReadOTPData(InstancePtr,
|
|
ReadParamPtr->Address,
|
|
ReadParamPtr->ReadPtr,
|
|
ReadParamPtr->NumBytes);
|
|
break;
|
|
|
|
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \
|
|
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
|
|
case XISF_DUAL_OP_FAST_READ:
|
|
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
|
Status = FastReadData(InstancePtr,
|
|
XISF_CMD_DUAL_OP_FAST_READ,
|
|
ReadParamPtr->Address,
|
|
ReadParamPtr->ReadPtr,
|
|
ReadParamPtr->NumBytes,
|
|
ReadParamPtr->NumDummyBytes);
|
|
break;
|
|
|
|
case XISF_DUAL_IO_FAST_READ:
|
|
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
|
Status = FastReadData(InstancePtr,
|
|
XISF_CMD_DUAL_IO_FAST_READ,
|
|
ReadParamPtr->Address,
|
|
ReadParamPtr->ReadPtr,
|
|
ReadParamPtr->NumBytes,
|
|
ReadParamPtr->NumDummyBytes);
|
|
break;
|
|
|
|
case XISF_QUAD_OP_FAST_READ:
|
|
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
|
Status = FastReadData(InstancePtr,
|
|
XISF_CMD_QUAD_OP_FAST_READ,
|
|
ReadParamPtr->Address,
|
|
ReadParamPtr->ReadPtr,
|
|
ReadParamPtr->NumBytes,
|
|
ReadParamPtr->NumDummyBytes);
|
|
break;
|
|
|
|
case XISF_QUAD_IO_FAST_READ:
|
|
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
|
|
Xil_AssertNonvoid(ReadParamPtr != NULL);
|
|
Status = FastReadData(InstancePtr,
|
|
XISF_CMD_QUAD_IO_FAST_READ,
|
|
ReadParamPtr->Address,
|
|
ReadParamPtr->ReadPtr,
|
|
ReadParamPtr->NumBytes,
|
|
ReadParamPtr->NumDummyBytes);
|
|
break;
|
|
#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) ||
|
|
(XPAR_XISF_FLASH_FAMILY == STM) ||
|
|
(XPAR_XISF_FLASH_FAMILY == SPANSION))*/
|
|
|
|
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 reads data from the Serial Flash.
|
|
*
|
|
* @param InstancePtr is a pointer to the XIsf instance.
|
|
* @param Address is the starting address in the Serial Flash from where
|
|
* the data is to be read.
|
|
* @param ReadPtr is a pointer to the memory where the data read from
|
|
* the Serial Flash is stored.
|
|
* @param ByteCount is the number of bytes to be read from the Serial
|
|
* Flash.
|
|
*
|
|
* @return XST_SUCCESS if successful else XST_FAILURE.
|
|
*
|
|
* @note
|
|
* - This operation is supported for Atmel, Intel, STM, Winbond
|
|
* and Spansion Serial Flash.
|
|
* - Minimum of one byte and a maximum of an entire Serial Flash
|
|
* Array can be read.
|
|
* - The valid data is available from the fourth location pointed
|
|
* to by the ReadPtr.
|
|
*
|
|
******************************************************************************/
|
|
static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount)
|
|
{
|
|
u8 Mode;
|
|
u32 BankSel;
|
|
u32 RealAddr;
|
|
int Status;
|
|
u32 RealByteCnt;
|
|
u32 BufferIndex;
|
|
u8 ShiftSize;
|
|
u32 TotalByteCnt = ByteCount;
|
|
u32 LocalByteCnt = ByteCount;
|
|
u32 LocalAddress = Address;
|
|
u8 WriteBuffer[5] = {0};
|
|
if (LocalByteCnt <= 0 ) {
|
|
return (int)XST_FAILURE;
|
|
}
|
|
|
|
if (ReadPtr == NULL) {
|
|
return (int)XST_FAILURE;
|
|
}
|
|
|
|
while(((s32)(LocalByteCnt)) > 0) {
|
|
|
|
/*
|
|
* Translate address based on type of connection
|
|
* If stacked assert the slave select based on address
|
|
*/
|
|
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress);
|
|
|
|
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
|
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);
|
|
|
|
BankSel = RealAddr/SIXTEENMB;
|
|
|
|
(void)SendBankSelect(InstancePtr, BankSel);
|
|
|
|
/*
|
|
* Restoring the transfer mode back
|
|
*/
|
|
XIsf_SetTransferMode(InstancePtr, Mode);
|
|
}
|
|
|
|
/*
|
|
* If data to be read spans beyond the current bank, then
|
|
* calculate RealByteCnt in current bank. Else
|
|
* RealByteCnt is the same as ByteCount
|
|
*/
|
|
if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) {
|
|
RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr;
|
|
}
|
|
else {
|
|
#endif
|
|
RealByteCnt = LocalByteCnt;
|
|
|
|
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
|
}
|
|
#endif
|
|
|
|
WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ;
|
|
WriteBuffer[BYTE2] = (u8)((RealAddr & 0xFF0000) >> XISF_ADDR_SHIFT16);
|
|
WriteBuffer[BYTE3] = (u8)((RealAddr & 0xFF00) >> XISF_ADDR_SHIFT8);
|
|
WriteBuffer[BYTE4] = (u8)(RealAddr & 0xFF);
|
|
|
|
Status = XIsf_Transfer(InstancePtr, WriteBuffer,
|
|
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
|
|
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES);
|
|
if (Status != (int)(XST_SUCCESS)) {
|
|
return (int)XST_FAILURE;
|
|
}
|
|
|
|
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
|
/*
|
|
* To discard the first 4 dummy bytes, shift the data in read buffer
|
|
*/
|
|
ShiftSize = XISF_CMD_SEND_EXTRA_BYTES;
|
|
BufferIndex = (TotalByteCnt - LocalByteCnt);
|
|
for(;
|
|
BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt);
|
|
BufferIndex++) {
|
|
ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize];
|
|
}
|
|
|
|
/*
|
|
* Increase address to next bank
|
|
*/
|
|
LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB;
|
|
#endif
|
|
/*
|
|
* Decrease byte count by bytes already read.
|
|
*/
|
|
LocalByteCnt = LocalByteCnt - RealByteCnt;
|
|
|
|
}
|
|
|
|
return (int)XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function reads data from the Serial Flash at a higher speed than normal
|
|
* Read operation.
|
|
*
|
|
* @param InstancePtr is a pointer to the XIsf instance.
|
|
* @param Command is the fast read command used to read data from the
|
|
* flash. It could be one of XISF_CMD_DUAL/QUAD_*_FAST_READ or
|
|
* XISF_CMD_FAST_READ.
|
|
* @param Address is the starting address in the Serial Flash from where
|
|
* the data is to be read.
|
|
* @param ReadPtr is a pointer to the memory where the data read from
|
|
* the Serial Flash is stored.
|
|
* @param ByteCount is the number of bytes to be read from the Serial
|
|
* Flash.
|
|
* @param NumDummyBytes is the number of dummy bytes associated with the
|
|
* fast read commands.
|
|
*
|
|
* @return XST_SUCCESS if successful else XST_FAILURE.
|
|
*
|
|
* @note
|
|
* - XISF_CMD_FAST_READ operation is supported for Atmel, Intel,
|
|
* STM, Winbond and Spansion Serial Flash.
|
|
* - XISF_CMD_DUAL/QUAD_*_FAST_READ operations are supported on
|
|
* Winbond (W25QXX), Numonyx (N25QXX) and Spansion (S25FL129)
|
|
* quad flash devices.
|
|
* - Minimum of one byte and a maximum of an entire Serial Flash
|
|
* Array can be read.
|
|
* - The valid data is available from the (4 + NumDummyBytes)th
|
|
* location pointed to by the ReadPtr.
|
|
*
|
|
******************************************************************************/
|
|
static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address,
|
|
u8 *ReadPtr, u32 ByteCount, int NumDummyBytes)
|
|
{
|
|
u8 Mode;
|
|
int Index;
|
|
int Status;
|
|
u32 BankSel;
|
|
u32 RealAddr;
|
|
u32 RealByteCnt;
|
|
u32 BufferIndex;
|
|
u8 ShiftSize;
|
|
u32 TotalByteCnt = ByteCount;
|
|
u32 LocalByteCnt = ByteCount;
|
|
u32 LocalAddress = Address;
|
|
u8 WriteBuffer[5]= {0};
|
|
|
|
if (LocalByteCnt <= 0 ) {
|
|
return (int)XST_FAILURE;
|
|
}
|
|
|
|
if (ReadPtr == NULL) {
|
|
return (int)(XST_FAILURE);
|
|
}
|
|
|
|
if (NumDummyBytes <= 0) {
|
|
return (int)(XST_FAILURE);
|
|
}
|
|
|
|
while(((s32)(LocalByteCnt)) > 0) {
|
|
|
|
/*
|
|
* Translate address based on type of connection
|
|
* If stacked assert the slave select based on address
|
|
*/
|
|
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress);
|
|
|
|
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
|
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);
|
|
|
|
BankSel = RealAddr/SIXTEENMB;
|
|
|
|
(void)SendBankSelect(InstancePtr, BankSel);
|
|
|
|
/*
|
|
* Restoring the transfer mode back
|
|
*/
|
|
XIsf_SetTransferMode(InstancePtr, Mode);
|
|
}
|
|
|
|
/*
|
|
* If data to be read spans beyond the current bank, then
|
|
* calculate RealByteCnt in current bank. Else
|
|
* RealByteCnt is the same as ByteCount
|
|
*/
|
|
if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) {
|
|
RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr;
|
|
}
|
|
else {
|
|
#endif
|
|
RealByteCnt = LocalByteCnt;
|
|
|
|
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
|
}
|
|
#endif
|
|
|
|
WriteBuffer[BYTE1] = Command;
|
|
WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
|
|
WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
|
|
WriteBuffer[BYTE4] = (u8) RealAddr;
|
|
|
|
for (Index = 0; Index < NumDummyBytes; Index++) {
|
|
WriteBuffer[Index + BYTE5] = (u8) (XISF_DUMMYBYTE);
|
|
}
|
|
|
|
RealByteCnt += NumDummyBytes;
|
|
|
|
/*
|
|
* Initiate the Transfer.
|
|
*/
|
|
Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer,
|
|
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
|
|
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES);
|
|
if (Status != (int)(XST_SUCCESS)) {
|
|
return (int)(XST_FAILURE);
|
|
}
|
|
|
|
#ifdef XPAR_XISF_INTERFACE_PSQSPI
|
|
/*
|
|
* To discard the first 5 dummy bytes, shift the data in read buffer
|
|
*/
|
|
ShiftSize = XISF_CMD_SEND_EXTRA_BYTES + (u8)NumDummyBytes;
|
|
BufferIndex = (TotalByteCnt - LocalByteCnt);
|
|
for(;
|
|
BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt);
|
|
BufferIndex++) {
|
|
ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize];
|
|
}
|
|
|
|
/*
|
|
* Increase address to next bank
|
|
*/
|
|
LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB;
|
|
#endif
|
|
/*
|
|
* Decrease byte count by bytes already read.
|
|
*/
|
|
LocalByteCnt = LocalByteCnt - (RealByteCnt - NumDummyBytes);
|
|
}
|
|
|
|
return (int)XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function copies the data from the Serial Flash to the specified SRAM
|
|
* buffer.
|
|
*
|
|
* @param InstancePtr is a pointer to the XIsf instance.
|
|
* @param BufferNum specifies the internal SRAM Buffer to which the data
|
|
* from Serial Flash is to be transferred. The valid values are
|
|
* XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is
|
|
* not valid in the case of AT45DB011D Flash as it contains a
|
|
* single buffer.
|
|
* @param Address specifies any address within the Page of the Serial
|
|
* Flash from where the Page of data is to be copied.
|
|
* Byte address in this Address is ignored as an entire Page of
|
|
* data is transferred/copied.
|
|
*
|
|
* @return XST_SUCCESS if successful else XST_FAILURE.
|
|
*
|
|
* @note
|
|
* - This operation is only supported in Atmel Serial Flash.
|
|
* - This function reads one complete Page from the Serial Flash.
|
|
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
|
|
* AT45XXXD Data sheets for more information.
|
|
*
|
|
******************************************************************************/
|
|
static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address)
|
|
{
|
|
int Status = (int)(XST_FAILURE);
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(Address != 0);
|
|
Xil_AssertNonvoid(BufferNum != 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) {
|
|
/*
|
|
* Page to Buffer 1 Transfer.
|
|
*/
|
|
InstancePtr->WriteBufPtr[BYTE1] =
|
|
XISF_CMD_PAGETOBUF1_TRANS;
|
|
} else {
|
|
/*
|
|
* Page to Buffer 2 Transfer.
|
|
*/
|
|
InstancePtr->WriteBufPtr[BYTE1] =
|
|
XISF_CMD_PAGETOBUF2_TRANS;
|
|
}
|
|
|
|
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 reads the data available in the SRAM buffer of Serial Flash.
|
|
*
|
|
* @param InstancePtr is a pointer to the XIsf instance.
|
|
* @param BufferNum specifies the internal SRAM Buffer from which data
|
|
* is to be read. 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.
|
|
* @param ReadPtr is a pointer to the memory where the data read from the
|
|
* SRAM buffer is stored.
|
|
* @param ByteOffset is the byte offset in the buffer from where the
|
|
* first byte is read.
|
|
* @param NumBytes is the number of bytes to be read from the Buffer.
|
|
*
|
|
* @return XST_SUCCESS if successful else XST_FAILURE.
|
|
*
|
|
* @note
|
|
* - This operation is only supported in Atmel Serial Flash.
|
|
* - This function reads a Minimum of one Byte and a Maximum of an
|
|
* entire SRAM buffer (1 Page) from the Serial Flash.
|
|
* - The valid data is available from the fourth location pointed
|
|
* to by the ReadPtr.
|
|
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
|
|
* AT45XXXD Data sheets for more information.
|
|
*
|
|
******************************************************************************/
|
|
static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
|
u32 ByteOffset, u32 NumBytes)
|
|
{
|
|
int Status = (int)(XST_FAILURE);
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(BufferNum != 0);
|
|
Xil_AssertNonvoid(ReadPtr != NULL);
|
|
Xil_AssertNonvoid(ByteOffset != 0);
|
|
Xil_AssertNonvoid(NumBytes != 0);
|
|
|
|
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
|
|
|
/*
|
|
* Check if 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 (ReadPtr == 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) {
|
|
ReadPtr[BYTE1] = XISF_CMD_BUF1_READ; /* Buffer 1 Read. */
|
|
} else {
|
|
ReadPtr[BYTE1] = XISF_CMD_BUF2_READ; /* Buffer 2 Read.*/
|
|
}
|
|
ReadPtr[BYTE2] = (u8) (0x00);
|
|
ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
|
|
ReadPtr[BYTE4] = (u8) ByteOffset;
|
|
|
|
/*
|
|
* Initiate the Transfer.
|
|
*/
|
|
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
|
|
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 reads the data from the internal SRAM page buffer of the Serial
|
|
* Flash memory at higher speed than normal Buffer Read operation.
|
|
*
|
|
* @param InstancePtr is a pointer to the XIsf instance.
|
|
* @param BufferNum specifies the internal SRAM Buffer from which data
|
|
* is to be read. 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.
|
|
* @param ReadPtr is a pointer to the memory where the data read from the
|
|
* SRAM buffer is stored.
|
|
* @param ByteOffset is the byte offset in the buffer from where the
|
|
* first byte is read.
|
|
* @param NumBytes is the number of bytes to be read from the Buffer.
|
|
*
|
|
* @return XST_SUCCESS if successful else XST_FAILURE.
|
|
*
|
|
* @note
|
|
* - This operation is only supported in Atmel Serial Flash.
|
|
* - This function reads a Minimum of one Byte and a Maximum of an
|
|
* entire SRAM buffer (1 Page) from the Serial Flash.
|
|
* - The valid data is available from the fifth location pointed
|
|
* to by the ReadPtr.
|
|
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
|
|
* AT45XXXD Data sheets for more information.
|
|
*
|
|
******************************************************************************/
|
|
static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
|
|
u32 ByteOffset, u32 NumBytes)
|
|
{
|
|
int Status = (int)(XST_FAILURE);
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(BufferNum != 0);
|
|
Xil_AssertNonvoid(ReadPtr != NULL);
|
|
Xil_AssertNonvoid(ByteOffset != 0);
|
|
Xil_AssertNonvoid(NumBytes != 0);
|
|
|
|
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
|
|
/*
|
|
* Check if 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 (ReadPtr == 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) {
|
|
/*
|
|
* Buffer 1 Fast Read.
|
|
*/
|
|
ReadPtr[BYTE1] = XISF_CMD_FAST_BUF1_READ;
|
|
} else {
|
|
/*
|
|
* Buffer 2 Fast Read.
|
|
*/
|
|
ReadPtr[BYTE1] = XISF_CMD_FAST_BUF2_READ;
|
|
}
|
|
|
|
ReadPtr[BYTE2] = (u8) (0x00);
|
|
ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
|
|
ReadPtr[BYTE4] = (u8) ByteOffset;
|
|
ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE);
|
|
|
|
/*
|
|
* Initiate the Transfer.
|
|
*/
|
|
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
|
|
NumBytes + XISF_CMD_FAST_READ_EXTRA_BYTES);
|
|
if (Status != (int)(XST_SUCCESS)) {
|
|
return (int)(XST_FAILURE);
|
|
}
|
|
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
|
|
|
|
return Status;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function reads the data from OTP area of the Serial Flash.
|
|
*
|
|
* @param InstancePtr is a pointer to the XIsf instance.
|
|
* @param Address is the starting address in OTP area of the Serial Flash
|
|
* from which the data is to be read.
|
|
* @param ReadPtr is a pointer to the memory where the data read from the
|
|
* Serial Flash is stored.
|
|
* @param ByteCount is the number of bytes to be read from the Serial
|
|
* Flash.
|
|
*
|
|
* @return XST_SUCCESS if successful else XST_FAILURE.
|
|
*
|
|
* @note
|
|
* - This operation is only supported for Intel Serial Flash.
|
|
* - Minimum of one byte and a maximum of an entire Serial Flash
|
|
* array can be read.
|
|
******************************************************************************/
|
|
static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
|
|
u32 ByteCount)
|
|
{
|
|
int Status = (int)(XST_FAILURE);
|
|
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid(Address != 0);
|
|
Xil_AssertNonvoid(ReadPtr != NULL);
|
|
Xil_AssertNonvoid(ByteCount != 0);
|
|
|
|
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
|
|
if (ByteCount <= 0 ) {
|
|
return (int)(XST_FAILURE);
|
|
}
|
|
|
|
if (ReadPtr == NULL) {
|
|
return (int)(XST_FAILURE);
|
|
}
|
|
|
|
ReadPtr[BYTE1] = XISF_CMD_OTP_READ;
|
|
ReadPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
|
|
ReadPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
|
|
ReadPtr[BYTE4] = (u8) Address;
|
|
ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE);
|
|
|
|
|
|
/*
|
|
* Initiate the Transfer.
|
|
*/
|
|
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
|
|
ByteCount + XISF_OTP_RDWR_EXTRA_BYTES);
|
|
if (Status != (int)(XST_SUCCESS)) {
|
|
return (int)(XST_FAILURE);
|
|
}
|
|
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
|
|
|
|
return Status;
|
|
}
|