/****************************************************************************** * Copyright (C) 2020 - 2022 Xilinx, Inc. All rights reserved. * SPDX-License-Identifier: MIT ******************************************************************************/ /*****************************************************************************/ /** * * @file xqspipsu_hw.c * @addtogroup Overview * @{ * * This file contains functions to reads RXFifo, writes TXFifo and setup * RX DMA operation, used by xqspipsu_control.c and xqspipsu_lowlevel.c files. * *
 * MODIFICATION HISTORY:
 *
 * Ver   Who Date     Changes
 * ----- --- -------- -----------------------------------------------
 * 1.11   akm  03/09/20 First release
 *         mn  03/30/20 Add xil_smc.h include for Xil_Smc calls
 * 1.13   akm  01/04/21 Fix MISRA-C violations.
 * 1.15   akm  10/21/21 Fix MISRA-C violations.
 * 1.15   akm  11/16/21 Typecast function parameter with appropriate
 * 			data type.
 * 1.15   akm  11/30/21 Fix compilation warnings reported with -Wundef flag
 * 1.15   akm  03/03/22 Enable tapdelay settings for applications on
 * 			 Microblaze platform.
 *
 * 
******************************************************************************/ /***************************** Include Files *********************************/ #include "xqspipsu.h" #include "xqspipsu_control.h" #if defined (__aarch64__) #include "xil_smc.h" #endif /************************** Constant Definitions *****************************/ /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ /************************** Function Prototypes ******************************/ /************************** Variable Definitions *****************************/ /*****************************************************************************/ /*****************************************************************************/ /** * * Fills the TX FIFO as long as there is room in the FIFO or the bytes required * to be transmitted. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * @param Size is the number of bytes to be transmitted. * * @return None * * @note None. * ******************************************************************************/ void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 Size) { u32 Count = 0; u32 Data = 0U; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(Size != 0U); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_FillTxFifo\r\n"); #endif while ((InstancePtr->TxBytes > 0) && (Count < Size)) { if (InstancePtr->TxBytes >= 4) { (void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr, 4); Msg->TxBfrPtr += 4; InstancePtr->TxBytes -= 4; Count += 4U; } else { (void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr, (u32)InstancePtr->TxBytes); Msg->TxBfrPtr += InstancePtr->TxBytes; Count += (u32)InstancePtr->TxBytes; InstancePtr->TxBytes = 0; } XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_TXD_OFFSET, Data); #ifdef DEBUG xil_printf("\nData is %08x\r\n", Data); #endif } if (InstancePtr->TxBytes < 0) { InstancePtr->TxBytes = 0; } } /*****************************************************************************/ /** * * This function checks the TX buffer in the message and setup the * TX FIFO as required. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * * @return None * * @note None. * ******************************************************************************/ void XQspiPsu_TXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_TXSetup\r\n"); #endif InstancePtr->TxBytes = (s32)Msg->ByteCount; InstancePtr->SendBufferPtr = Msg->TxBfrPtr; XQspiPsu_FillTxFifo(InstancePtr, Msg, (u32)XQSPIPSU_TXD_DEPTH); } /*****************************************************************************/ /** * * This function sets up the RX DMA operation. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * * @return None * * @note None. * ******************************************************************************/ void XQspiPsu_SetupRxDma(const XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg) { s32 Remainder; s32 DmaRxBytes; UINTPTR AddrTemp; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_SetupRxDma\r\n"); #endif AddrTemp = ((UINTPTR)(Msg->RxBfrPtr) & XQSPIPSU_QSPIDMA_DST_ADDR_MASK); /* Check for RXBfrPtr to be word aligned */ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET, (u32)AddrTemp); #if defined(__aarch64__) || defined(__arch64__) AddrTemp = ((UINTPTR)(Msg->RxBfrPtr) >> 32U); XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp & XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK); #else XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, 0U); #endif Remainder = InstancePtr->RxBytes % 4; DmaRxBytes = InstancePtr->RxBytes; if (Remainder != 0) { /* This is done to make Dma bytes aligned */ DmaRxBytes = InstancePtr->RxBytes - Remainder; Msg->ByteCount = (u32)DmaRxBytes; } if (InstancePtr->Config.IsCacheCoherent == 0U) { Xil_DCacheInvalidateRange((INTPTR)Msg->RxBfrPtr, (INTPTR)Msg->ByteCount); } /* Write no. of words to DMA DST SIZE */ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes); } /*****************************************************************************/ /** * * This function sets up the RX DMA operation on a 32bit Machine * For 64bit Dma transfers. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * * @return None * * @note None. * ******************************************************************************/ void XQspiPsu_Setup64BRxDma(const XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg) { s32 Remainder; s32 DmaRxBytes; u64 AddrTemp; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_Setup64BRxDma\r\n"); #endif AddrTemp = Msg->RxAddr64bit & XQSPIPSU_QSPIDMA_DST_ADDR_MASK; XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET, (u32)AddrTemp); AddrTemp = (Msg->RxAddr64bit >> 32); XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp & XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK); Remainder = InstancePtr->RxBytes % 4; DmaRxBytes = InstancePtr->RxBytes; if (Remainder != 0) { /* This is done to make Dma bytes aligned */ DmaRxBytes = InstancePtr->RxBytes - Remainder; Msg->ByteCount = (u32)DmaRxBytes; } /* Write no. of words to DMA DST SIZE */ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes); } /*****************************************************************************/ /** * * This function reads remaining bytes, after the completion of a DMA transfer, * using IO mode * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * * @return * - XST_SUCCESS if successful. * - XST_FAILURE if transfer fails. * - XST_DEVICE_BUSY if a transfer is already in progress. * * @note None. * ******************************************************************************/ u32 XQspiPsu_SetIOMode(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg) { Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(Msg != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_DMARXComplete\r\n"); #endif /* Read remaining bytes using IO mode */ if ((InstancePtr->RxBytes % 4) != 0) { XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) & ~XQSPIPSU_CFG_MODE_EN_MASK)); InstancePtr->ReadMode = XQSPIPSU_READMODE_IO; Msg->ByteCount = (u32)InstancePtr->RxBytes % 4U; Msg->RxBfrPtr += (InstancePtr->RxBytes - (InstancePtr->RxBytes % 4)); InstancePtr->IsUnaligned = 1; return (u32) TRUE; } return (u32) FALSE; } /*****************************************************************************/ /** * * This function checks the RX buffers in the message and setup the * RX DMA as required. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * * @return None * * @note None. * ******************************************************************************/ void XQspiPsu_RXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_RXSetup\r\n"); #endif InstancePtr->RxBytes = (s32)Msg->ByteCount; if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) { if ((Msg->RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) || (Msg->Xfer64bit != (u8)0U)) { XQspiPsu_Setup64BRxDma(InstancePtr, Msg); } else { XQspiPsu_SetupRxDma(InstancePtr, Msg); } } } /*****************************************************************************/ /** * * This function checks the TX/RX buffers in the message and setups up the * GENFIFO entries, TX FIFO or RX DMA as required. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * @param GenFifoEntry is pointer to the variable in which GENFIFO mask * is returned to calling function * * @return None * * @note None. * ******************************************************************************/ void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 *GenFifoEntry) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(GenFifoEntry != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_TXRXSetup\r\n"); #endif /* Transmit */ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) && ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) { *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER; *GenFifoEntry |= XQSPIPSU_GENFIFO_TX; /* Discard RX data */ *GenFifoEntry &= ~XQSPIPSU_GENFIFO_RX; /* Setup data to be TXed */ XQspiPsu_TXSetup(InstancePtr, Msg); InstancePtr->RecvBufferPtr = NULL; InstancePtr->RxBytes = 0; } /*Receive*/ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE) && ((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE)) { /* TX auto fill */ *GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX; /* Setup RX */ *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER; *GenFifoEntry |= XQSPIPSU_GENFIFO_RX; /* Setup DMA for data to be RXed */ XQspiPsu_RXSetup(InstancePtr, Msg); InstancePtr->SendBufferPtr = NULL; InstancePtr->TxBytes = 0; } /* If only dummy is requested as a separate entry */ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE) && ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) { *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER; *GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX); InstancePtr->TxBytes = 0; InstancePtr->RxBytes = 0; InstancePtr->SendBufferPtr = NULL; InstancePtr->RecvBufferPtr = NULL; } /* Dummy and cmd sent by upper layer to received data */ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) && ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) { *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER; *GenFifoEntry |= (XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX); /* Setup data to be TXed */ XQspiPsu_TXSetup(InstancePtr, Msg); /* Setup DMA for data to be RXed */ XQspiPsu_RXSetup(InstancePtr, Msg); } } /*****************************************************************************/ /** * * This function writes the Data length to GENFIFO entries that need to be * transmitted or received. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * @param GenFifoEntry is index of the current message to be handled. * * @return * - XST_SUCCESS if successful. * - XST_FAILURE if transfer fails. * - XST_DEVICE_BUSY if a transfer is already in progress. * * @note None. * ******************************************************************************/ void XQspiPsu_GenFifoEntryDataLen(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 *GenFifoEntry) { u32 TempCount; u32 ImmData; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(GenFifoEntry != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_GenFifoEntryDataLen\r\n"); #endif if (Msg->ByteCount <= XQSPIPSU_GENFIFO_IMM_DATA_MASK) { *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK; *GenFifoEntry |= Msg->ByteCount; #ifdef DEBUG xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry); #endif XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, *GenFifoEntry); } else { TempCount = Msg->ByteCount; u32 Exponent = 8; /* 2^8 = 256 */ ImmData = TempCount & 0xFFU; /* Exponent entries */ *GenFifoEntry |= XQSPIPSU_GENFIFO_EXP; while (TempCount != 0U) { if ((TempCount & XQSPIPSU_GENFIFO_EXP_START) != (u32)FALSE) { *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK; *GenFifoEntry |= Exponent; #ifdef DEBUG xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry); #endif XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, *GenFifoEntry); } TempCount = TempCount >> 1; Exponent++; } /* Immediate entry */ *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_EXP; if ((ImmData & 0xFFU) != (u32)FALSE) { *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK; *GenFifoEntry |= ImmData & 0xFFU; #ifdef DEBUG xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry); #endif XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, *GenFifoEntry); } } } /*****************************************************************************/ /** * * This function creates Poll config register data to write * * @param InstancePtr is a pointer to the XQspiPsu instance. * * @param FlashMsg is a pointer to the structure containing transfer data. * * @return None * * @note None. * ******************************************************************************/ u32 XQspiPsu_CreatePollDataConfig(const XQspiPsu *InstancePtr, const XQspiPsu_Msg *FlashMsg) { u32 ConfigData = 0; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(FlashMsg != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_CreatePollDataConfig\r\n"); #endif if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_UPPER) != (u32)FALSE) { ConfigData = (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER << XQSPIPSU_POLL_CFG_EN_MASK_UPPER_SHIFT; } if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_LOWER) != (u32)FALSE) { ConfigData |= (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER << XQSPIPSU_POLL_CFG_EN_MASK_LOWER_SHIFT; } ConfigData |= (u32)(((u32)FlashMsg->PollBusMask << XQSPIPSU_POLL_CFG_MASK_EN_SHIFT) & XQSPIPSU_POLL_CFG_MASK_EN_MASK); ConfigData |= (u32)(((u32)FlashMsg->PollData << XQSPIPSU_POLL_CFG_DATA_VALUE_SHIFT) & XQSPIPSU_POLL_CFG_DATA_VALUE_MASK); return ConfigData; } /*****************************************************************************/ /** * * Selects SPI mode - x1 or x2 or x4. * * @param SpiMode - spi or dual or quad. * @return Mask to set desired SPI mode in GENFIFO entry. * * @note None. * ******************************************************************************/ u32 XQspiPsu_SelectSpiMode(u8 SpiMode) { u32 Mask; Xil_AssertNonvoid(SpiMode > 0U); #ifdef DEBUG xil_printf("\nXQspiPsu_SelectSpiMode\r\n"); #endif switch (SpiMode) { case XQSPIPSU_SELECT_MODE_DUALSPI: Mask = XQSPIPSU_GENFIFO_MODE_DUALSPI; break; case XQSPIPSU_SELECT_MODE_QUADSPI: Mask = XQSPIPSU_GENFIFO_MODE_QUADSPI; break; case XQSPIPSU_SELECT_MODE_SPI: Mask = XQSPIPSU_GENFIFO_MODE_SPI; break; default: Mask = XQSPIPSU_GENFIFO_MODE_SPI; break; } #ifdef DEBUG xil_printf("\nSPIMode is %08x\r\n", SpiMode); #endif return Mask; } /*****************************************************************************/ /** * * Enable and initialize DMA Mode, set little endain, disable poll timeout, * clear prescalar bits and reset thresholds * * @param InstancePtr is a pointer to the XQspiPsu instance. * * @return None. * * @note None. * ******************************************************************************/ void XQspiPsu_SetDefaultConfig(XQspiPsu *InstancePtr) { u32 ConfigReg; Xil_AssertVoid(InstancePtr != NULL); #ifdef DEBUG xil_printf("\nXQspiPsu_SetDefaultConfig\r\n"); #endif /* Default value to config register */ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET); /* DMA mode */ ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK; ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK; /* Manual start */ ConfigReg |= XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK; /* Little endain by default */ ConfigReg &= ~XQSPIPSU_CFG_ENDIAN_MASK; /* Disable poll timeout */ ConfigReg &= ~XQSPIPSU_CFG_EN_POLL_TO_MASK; /* Set hold bit */ ConfigReg |= XQSPIPSU_CFG_WP_HOLD_MASK; /* Clear prescalar by default */ ConfigReg &= ~(u32)XQSPIPSU_CFG_BAUD_RATE_DIV_MASK; /* CPOL CPHA 00 */ ConfigReg &= ~(u32)XQSPIPSU_CFG_CLK_PHA_MASK; ConfigReg &= ~(u32)XQSPIPSU_CFG_CLK_POL_MASK; XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET, ConfigReg); /* Set by default to allow for high frequencies */ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_LPBK_DLY_ADJ_OFFSET, XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_LPBK_DLY_ADJ_OFFSET) | XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK); /* Reset thresholds */ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_TX_THRESHOLD_OFFSET, XQSPIPSU_TX_FIFO_THRESHOLD_RESET_VAL); XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_RX_THRESHOLD_OFFSET, XQSPIPSU_RX_FIFO_THRESHOLD_RESET_VAL); XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GF_THRESHOLD_OFFSET, XQSPIPSU_GEN_FIFO_THRESHOLD_RESET_VAL); /* DMA init */ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET, XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL); } /*****************************************************************************/ /** * * Read the specified number of bytes from RX FIFO * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * @param Size is the number of bytes to be read. * * @return None * * @note None. * ******************************************************************************/ void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, s32 Size) { s32 Count = 0; u32 Data; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(Size > 0); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_ReadRxFifo\r\n"); #endif while ((InstancePtr->RxBytes != 0) && (Count < Size)) { Data = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_RXD_OFFSET); #ifdef DEBUG xil_printf("\nData is %08x\r\n", Data); #endif if (InstancePtr->RxBytes >= 4) { (void)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data, 4); InstancePtr->RxBytes -= 4; Msg->RxBfrPtr += 4; Count += 4; } else { /* Read unaligned bytes (< 4 bytes) */ (void)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data, (u32)InstancePtr->RxBytes); Msg->RxBfrPtr += InstancePtr->RxBytes; Count += InstancePtr->RxBytes; InstancePtr->RxBytes = 0; } } } /*****************************************************************************/ /** * * This function reads data from RXFifo in IO mode. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param Msg is a pointer to the structure containing transfer data. * @param StatusReg is the Interrupt status Register value. * * @return None. * * @note None. * ******************************************************************************/ void XQspiPsu_IORead(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 StatusReg) { s32 RxThr; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Msg != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); #ifdef DEBUG xil_printf("\nXQspiPsu_IORXComplete\r\n"); #endif if ((StatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK) != 0U) { /* * Check if PIO RX is complete and * update RxBytes */ RxThr = (s32)XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_RX_THRESHOLD_OFFSET); RxThr = RxThr*4; XQspiPsu_ReadRxFifo(InstancePtr, Msg, RxThr); return; } if ((StatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) { XQspiPsu_ReadRxFifo(InstancePtr, Msg, InstancePtr->RxBytes); } } #if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__) /*****************************************************************************/ /** * * This function sets the Tapdelay values for the QSPIPSU device driver.The device * must be idle rather than busy transferring data before setting Tapdelay. * * @param InstancePtr is a pointer to the XQspiPsu instance. * @param TapdelayBypss contains the IOU_TAPDLY_BYPASS register value. * @param LPBKDelay contains the GQSPI_LPBK_DLY_ADJ register value. * @param Datadelay contains the QSPI_DATA_DLY_ADJ register value. * * @return * - XST_SUCCESS if options are successfully set. * - XST_DEVICE_BUSY if the device is currently transferring data. * The transfer must complete or be aborted before setting TapDelay. * * @note * This function is not thread-safe. * ******************************************************************************/ s32 XQspipsu_Set_TapDelay(const XQspiPsu *InstancePtr, u32 TapdelayBypass, u32 LPBKDelay, u32 Datadelay) { s32 Status; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Do not allow to modify the Control Register while a transfer is in * progress. Not thread-safe. */ if (InstancePtr->IsBusy == (u32)TRUE) { Status = (s32)XST_DEVICE_BUSY; } else { #if defined (__aarch64__) && (EL1_NONSECURE == 1) && !defined (versal) Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(XPS_SYS_CTRL_BASEADDR + IOU_TAPDLY_BYPASS_OFFSET) | ((u64)(0x4) << 32), (u64)TapdelayBypass, 0, 0, 0, 0, 0); #elif defined (versal) XQspiPsu_WriteReg(XQSPIPS_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET, TapdelayBypass); #else XQspiPsu_WriteReg(XPS_SYS_CTRL_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET, TapdelayBypass); #endif XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_LPBK_DLY_ADJ_OFFSET, LPBKDelay); XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_DATA_DLY_ADJ_OFFSET, Datadelay); Status = (s32)XST_SUCCESS; } return Status; } #endif /** @} */