📄 xqspips.c
字号:
/******************************************************************************** (c) Copyright 2010-12 Xilinx, Inc. All rights reserved.** This file contains confidential and proprietary information of Xilinx, Inc.* and is protected under U.S. and international copyright and other* intellectual property laws.** DISCLAIMER* This disclaimer is not a license and does not grant any rights to the* materials distributed herewith. Except as otherwise provided in a valid* license issued to you by Xilinx, and to the maximum extent permitted by* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;* and (2) Xilinx shall not be liable (whether in contract or tort, including* negligence, or under any other theory of liability) for any loss or damage* of any kind or nature related to, arising under or in connection with these* materials, including for any direct, or any indirect, special, incidental,* or consequential loss or damage (including loss of data, profits, goodwill,* or any type of loss or damage suffered as a result of any action brought by* a third party) even if such damage or loss was reasonably foreseeable or* Xilinx had been advised of the possibility of the same.** CRITICAL APPLICATIONS* Xilinx products are not designed or intended to be fail-safe, or for use in* any application requiring fail-safe performance, such as life-support or* safety devices or systems, Class III medical devices, nuclear facilities,* applications related to the deployment of airbags, or any other applications* that could lead to death, personal injury, or severe property or* environmental damage (individually and collectively, "Critical* Applications"). Customer assumes the sole risk and liability of any use of* Xilinx products in Critical Applications, subject only to applicable laws* and regulations governing limitations on product liability.** THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE* AT ALL TIMES.*******************************************************************************//*****************************************************************************//**** @file xqspips.c** Contains implements the interface functions of the XQspiPs driver.* See xqspips.h for a detailed description of the device and driver.** <pre>* MODIFICATION HISTORY:** Ver Who Date Changes* ----- --- -------- -----------------------------------------------* 1.00 sdm 11/25/10 First release** </pre>*******************************************************************************//***************************** Include Files *********************************/#include "xqspips.h"/************************** Constant Definitions *****************************//**************************** Type Definitions *******************************//** * This typedef defines qspi flash instruction format */typedef struct { u8 OpCode; /**< Operational code of the instruction */ u8 InstSize; /**< Size of the instruction including address bytes */ u8 TxOffset; /**< Register address where instruction has to be written */} XQspiPsInstFormat;/***************** Macros (Inline Functions) Definitions *********************/#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))/************************** Function Prototypes ******************************/static void XQspiPs_GetWriteData(XQspiPs *InstancePtr, u32 *Data, u8 Size);static void XQspiPs_GetReadData(XQspiPs *InstancePtr, u32 Data, u8 Size);static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, unsigned ByteCount);/************************** Variable Definitions *****************************//* * List of all the QSPI instructions and its format */static XQspiPsInstFormat FlashInst[] = { { XQSPIPS_FLASH_OPCODE_WREN, 1, XQSPIPS_TXD_01_OFFSET }, { XQSPIPS_FLASH_OPCODE_WRDS, 1, XQSPIPS_TXD_01_OFFSET }, { XQSPIPS_FLASH_OPCODE_RDSR1, 2, XQSPIPS_TXD_10_OFFSET }, { XQSPIPS_FLASH_OPCODE_RDSR2, 2, XQSPIPS_TXD_10_OFFSET }, { XQSPIPS_FLASH_OPCODE_WRSR, 2, XQSPIPS_TXD_10_OFFSET }, { XQSPIPS_FLASH_OPCODE_PP, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_SE, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_BE_32K, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_BE_4K, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_BE, 1, XQSPIPS_TXD_01_OFFSET }, { XQSPIPS_FLASH_OPCODE_ERASE_SUS, 1, XQSPIPS_TXD_01_OFFSET }, { XQSPIPS_FLASH_OPCODE_ERASE_RES, 1, XQSPIPS_TXD_01_OFFSET }, { XQSPIPS_FLASH_OPCODE_RDID, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_NORM_READ, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_FAST_READ, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_DUAL_READ, 4, XQSPIPS_TXD_00_OFFSET }, { XQSPIPS_FLASH_OPCODE_QUAD_READ, 4, XQSPIPS_TXD_00_OFFSET }, /* Add all the instructions supported by the flash device */};/*****************************************************************************//**** Initializes a specific XQspiPs instance such that the driver is ready to use.** The state of the device after initialization is:* - Master mode* - Active high clock polarity* - Clock phase 0* - Baud rate divisor 2* - Transfer width 32* - Master reference clock = pclk* - No chip select active* - Manual CS and Manual Start disabled** @param InstancePtr is a pointer to the XQspiPs instance.* @param ConfigPtr is a reference to a structure containing information* about a specific QSPI device. This function initializes an* InstancePtr object for a specific device specified by the* contents of Config. This function can initialize multiple* instance objects with the use of multiple calls giving different* Config information on each call.* @param EffectiveAddr is the device base address in the virtual memory* address space. The caller is responsible for keeping the address* mapping from EffectiveAddr to the device physical base address* unchanged once this function is invoked. Unexpected errors may* occur if the address mapping changes after this function is* called. If address translation is not used, use* ConfigPtr->Config.BaseAddress for this device.** @return* - XST_SUCCESS if successful.* - XST_DEVICE_IS_STARTED if the device is already started.* It must be stopped to re-initialize.** @note None.*******************************************************************************/int XQspiPs_CfgInitialize(XQspiPs *InstancePtr, XQspiPs_Config *ConfigPtr, u32 EffectiveAddr){ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(ConfigPtr != NULL); /* * If the device is busy, disallow the initialize and return a status * indicating it is already started. This allows the user to stop the * device and re-initialize, but prevents a user from inadvertently * initializing. This assumes the busy flag is cleared at startup. */ if (InstancePtr->IsBusy == TRUE) { return XST_DEVICE_IS_STARTED; } /* * Set some default values. */ InstancePtr->IsBusy = FALSE; InstancePtr->Config.BaseAddress = EffectiveAddr; InstancePtr->StatusHandler = StubStatusHandler; InstancePtr->SendBufferPtr = NULL; InstancePtr->RecvBufferPtr = NULL; InstancePtr->RequestedBytes = 0; InstancePtr->RemainingBytes = 0; InstancePtr->IsReady = XIL_COMPONENT_IS_READY; /* * Reset the QSPI device to get it into its initial state. It is * expected that device configuration will take place after this * initialization is done, but before the device is started. */ XQspiPs_Reset(InstancePtr); return XST_SUCCESS;}/*****************************************************************************//**** Resets the QSPI device. Reset must only be called after the driver has been* initialized. Any data transfer that is in progress is aborted.** The upper layer software is responsible for re-configuring (if necessary)* and restarting the QSPI device after the reset.** @param InstancePtr is a pointer to the XQspiPs instance.** @return None.** @note None.*******************************************************************************/void XQspiPs_Reset(XQspiPs *InstancePtr){ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Abort any transfer that is in progress */ XQspiPs_Abort(InstancePtr); /* * Reset any values that are not reset by the hardware reset such that * the software state matches the hardware device */ XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, XQSPIPS_CR_RESET_STATE);}/*****************************************************************************//**** Aborts a transfer in progress by disabling the device and resetting the FIFOs* if present. The byte counts are cleared, the busy flag is cleared, and mode* fault is cleared.** @param InstancePtr is a pointer to the XQspiPs instance.** @return None.** @note** This function does a read/modify/write of the control register. The user of* this function needs to take care of critical sections.*******************************************************************************/void XQspiPs_Abort(XQspiPs *InstancePtr){ XQspiPs_Disable(InstancePtr->Config.BaseAddress); /* * Clear the RX FIFO and drop any data. */ while ((XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET) & XQSPIPS_IXR_RXNEMPTY_MASK) != 0) { XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_RXD_OFFSET); } /* * Clear mode fault condition. */ XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_SR_OFFSET, XQSPIPS_IXR_MODF_MASK); InstancePtr->RemainingBytes = 0; InstancePtr->RequestedBytes = 0; InstancePtr->IsBusy = FALSE;}/*****************************************************************************//**** Transfers specified data on the QSPI bus. If the QSPI device is configured as* a master, this function initiates bus communication and sends/receives the* data to/from the selected QSPI slave. If the QSPI device is configured as a* slave, this function prepares the buffers to be sent/received when selected* by a master. For every byte sent, a byte is received.** The caller has the option of providing two different buffers for send and* receive, or one buffer for both send and receive, or no buffer for receive.* The receive buffer must be at least as big as the send buffer to prevent* unwanted memory writes. This implies that the byte count passed in as an* argument must be the smaller of the two buffers if they differ in size.* Here are some sample usages:* <pre>* XQspiPs_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount)* The caller wishes to send and receive, and provides two different* buffers for send and receive.** XQspiPs_Transfer(InstancePtr, SendBuf, NULL, ByteCount)* The caller wishes only to send and does not care about the received* data. The driver ignores the received data in this case.** XQspiPs_Transfer(InstancePtr, SendBuf, SendBuf, ByteCount)* The caller wishes to send and receive, but provides the same buffer* for doing both. The driver sends the data and overwrites the send* buffer with received data as it transfers the data.** XQspiPs_Transfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)* The caller wishes to only receive and does not care about sending* data. In this case, the caller must still provide a send buffer, but* it can be the same as the receive buffer if the caller does not care* what it sends. The device must send N bytes of data if it wishes to* receive N bytes of data.* </pre>* Although this function takes entire buffers as arguments, the driver can only* transfer a limited number of bytes at a time, limited by the size of the* FIFO. A call to this function only starts the transfer, then subsequent* transfers of the data is performed by the interrupt service routine until* the entire buffer has been transferred. The status callback function is* called when the entire buffer has been sent/received.** This function is non-blocking. As a master, the SetSlaveSelect function must* be called prior to this function.** @param InstancePtr is a pointer to the XQspiPs instance.* @param SendBufPtr is a pointer to a data buffer that needs to be* transmitted. This buffer must not be NULL.* @param RecvBufPtr is a pointer to a buffer for received data.* This argument can be NULL if do not care about receiving.* @param ByteCount contains the number of bytes to send/receive.* The number of bytes received always equals the number of bytes* sent.* @param IsInst specifies whether the first byte(s) in the transmit* buffer is a serial flash instruction.** @return* - XST_SUCCESS if the buffers are successfully handed off to the* device for transfer.* - XST_DEVICE_BUSY indicates that a data transfer is already in* progress. This is determined by the driver.** @note** This function is not thread-safe. The higher layer software must ensure that* no two threads are transferring data on the QSPI bus at the same time.*******************************************************************************/int XQspiPs_Transfer(XQspiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, unsigned ByteCount, int IsInst){ u32 ControlReg; u8 Instruction; u32 Data; unsigned int Index; XQspiPsInstFormat *CurrInst; /* * The RecvBufPtr argument can be null */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(SendBufPtr != NULL); Xil_AssertNonvoid(ByteCount > 0); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(IsInst <= XQSPIPS_IS_INST); /* * Check whether there is another transfer in progress. Not thread-safe. */ if (InstancePtr->IsBusy) { return XST_DEVICE_BUSY; } /* * Set the busy flag, which will be cleared in the ISR when the * transfer is entirely done. */ InstancePtr->IsBusy = TRUE; /* * Set up buffer pointers. */ InstancePtr->SendBufferPtr = SendBufPtr; InstancePtr->RecvBufferPtr = RecvBufPtr; InstancePtr->RequestedBytes = ByteCount; InstancePtr->RemainingBytes = ByteCount; /* * If the slave select lines are "Forced" or under manual control, * set the slave selects now, before beginning the transfer. */ ControlReg = XQspiPs_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET); if (0 != (ControlReg & XQSPIPS_CR_SSFORCE_MASK)) { ControlReg &= ~XQSPIPS_CR_SSCTRL_MASK; ControlReg |= InstancePtr->SlaveSelect; XQspiPs_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPS_CR_OFFSET, ControlReg); } /* * Enable the device. */ XQspiPs_Enable(InstancePtr->Config.BaseAddress); if (IsInst == 1) { Instruction = *InstancePtr->SendBufferPtr; for (Index = 0 ; Index < ARRAY_SIZE(FlashInst); Index++) { if (Instruction == FlashInst[Index].OpCode) { break; } } if (Index == ARRAY_SIZE(FlashInst)) { /* Instruction is not supported */ return XST_FAILURE; } CurrInst = &FlashInst[Index];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -