Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /******************************************************************************
0002 * Copyright (C) 2020 - 2022 Xilinx, Inc.  All rights reserved.
0003 * SPDX-License-Identifier: MIT
0004 ******************************************************************************/
0005 
0006 
0007 /*****************************************************************************/
0008 /**
0009  *
0010  * @file xqspipsu_hw.c
0011  * @addtogroup Overview
0012  * @{
0013  *
0014  * This file contains functions to reads RXFifo, writes TXFifo and setup
0015  * RX DMA operation, used by xqspipsu_control.c and xqspipsu_lowlevel.c files.
0016  *
0017  * <pre>
0018  * MODIFICATION HISTORY:
0019  *
0020  * Ver   Who Date     Changes
0021  * ----- --- -------- -----------------------------------------------
0022  * 1.11   akm  03/09/20 First release
0023  *         mn  03/30/20 Add xil_smc.h include for Xil_Smc calls
0024  * 1.13   akm  01/04/21 Fix MISRA-C violations.
0025  * 1.15   akm  10/21/21 Fix MISRA-C violations.
0026  * 1.15   akm  11/16/21 Typecast function parameter with appropriate
0027  *          data type.
0028  * 1.15   akm  11/30/21 Fix compilation warnings reported with -Wundef flag
0029  * 1.15   akm  03/03/22 Enable tapdelay settings for applications on
0030  *           Microblaze platform.
0031  *
0032  * </pre>
0033  ******************************************************************************/
0034 
0035 /***************************** Include Files *********************************/
0036 
0037 #include "xqspipsu.h"
0038 #include "xqspipsu_control.h"
0039 #ifndef __rtems__
0040 #if defined (__aarch64__)
0041 #include "xil_smc.h"
0042 #endif
0043 #else
0044 #include <bsp/xil-compat.h>
0045 #endif
0046 /************************** Constant Definitions *****************************/
0047 
0048 /**************************** Type Definitions *******************************/
0049 
0050 /***************** Macros (Inline Functions) Definitions *********************/
0051 
0052 /************************** Function Prototypes ******************************/
0053 
0054 /************************** Variable Definitions *****************************/
0055 
0056 /*****************************************************************************/
0057 
0058 /*****************************************************************************/
0059 /**
0060  *
0061  * Fills the TX FIFO as long as there is room in the FIFO or the bytes required
0062  * to be transmitted.
0063  *
0064  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0065  * @param   Msg is a pointer to the structure containing transfer data.
0066  * @param   Size is the number of bytes to be transmitted.
0067  *
0068  * @return  None
0069  *
0070  * @note    None.
0071  *
0072  ******************************************************************************/
0073 void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 Size)
0074 {
0075     u32 Count = 0;
0076     u32 Data = 0U;
0077 
0078     Xil_AssertVoid(InstancePtr != NULL);
0079     Xil_AssertVoid(Msg != NULL);
0080     Xil_AssertVoid(Size != 0U);
0081     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0082 #ifdef DEBUG
0083     xil_printf("\nXQspiPsu_FillTxFifo\r\n");
0084 #endif
0085     while ((InstancePtr->TxBytes > 0) && (Count < Size)) {
0086         if (InstancePtr->TxBytes >= 4) {
0087             (void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr, 4);
0088             Msg->TxBfrPtr += 4;
0089             InstancePtr->TxBytes -= 4;
0090             Count += 4U;
0091         } else {
0092             (void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr,
0093                 (u32)InstancePtr->TxBytes);
0094             Msg->TxBfrPtr += InstancePtr->TxBytes;
0095             Count += (u32)InstancePtr->TxBytes;
0096             InstancePtr->TxBytes = 0;
0097         }
0098         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0099                 XQSPIPSU_TXD_OFFSET, Data);
0100 #ifdef DEBUG
0101     xil_printf("\nData is %08x\r\n", Data);
0102 #endif
0103 
0104     }
0105     if (InstancePtr->TxBytes < 0) {
0106         InstancePtr->TxBytes = 0;
0107     }
0108 }
0109 
0110 /*****************************************************************************/
0111 /**
0112  *
0113  * This function checks the TX buffer in the message and setup the
0114  * TX FIFO as required.
0115  *
0116  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0117  * @param   Msg is a pointer to the structure containing transfer data.
0118  *
0119  * @return  None
0120  *
0121  * @note    None.
0122  *
0123  ******************************************************************************/
0124 void XQspiPsu_TXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
0125 {
0126     Xil_AssertVoid(InstancePtr != NULL);
0127     Xil_AssertVoid(Msg != NULL);
0128     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0129 #ifdef DEBUG
0130     xil_printf("\nXQspiPsu_TXSetup\r\n");
0131 #endif
0132     InstancePtr->TxBytes = (s32)Msg->ByteCount;
0133     InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
0134 
0135     XQspiPsu_FillTxFifo(InstancePtr, Msg, (u32)XQSPIPSU_TXD_DEPTH);
0136 }
0137 
0138 /*****************************************************************************/
0139 /**
0140  *
0141  * This function sets up the RX DMA operation.
0142  *
0143  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0144  * @param   Msg is a pointer to the structure containing transfer data.
0145  *
0146  * @return  None
0147  *
0148  * @note    None.
0149  *
0150  ******************************************************************************/
0151 void XQspiPsu_SetupRxDma(const XQspiPsu *InstancePtr,
0152                     XQspiPsu_Msg *Msg)
0153 {
0154     s32 Remainder;
0155     s32 DmaRxBytes;
0156     UINTPTR AddrTemp;
0157 
0158     Xil_AssertVoid(InstancePtr != NULL);
0159     Xil_AssertVoid(Msg != NULL);
0160     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0161 #ifdef DEBUG
0162     xil_printf("\nXQspiPsu_SetupRxDma\r\n");
0163 #endif
0164 
0165     AddrTemp = ((UINTPTR)(Msg->RxBfrPtr) & XQSPIPSU_QSPIDMA_DST_ADDR_MASK);
0166     /* Check for RXBfrPtr to be word aligned */
0167     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0168             XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET, (u32)AddrTemp);
0169 
0170 #if defined(__aarch64__) || defined(__arch64__)
0171     AddrTemp = ((UINTPTR)(Msg->RxBfrPtr) >> 32U);
0172     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0173             XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp &
0174             XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
0175 #else
0176     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0177             XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, 0U);
0178 #endif
0179 
0180     Remainder = InstancePtr->RxBytes % 4;
0181     DmaRxBytes = InstancePtr->RxBytes;
0182     if (Remainder != 0) {
0183         /* This is done to make Dma bytes aligned */
0184         DmaRxBytes = InstancePtr->RxBytes - Remainder;
0185         Msg->ByteCount = (u32)DmaRxBytes;
0186     }
0187     if (InstancePtr->Config.IsCacheCoherent == 0U) {
0188         Xil_DCacheInvalidateRange((INTPTR)Msg->RxBfrPtr, (INTPTR)Msg->ByteCount);
0189     }
0190     /* Write no. of words to DMA DST SIZE */
0191     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0192             XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
0193 }
0194 
0195 /*****************************************************************************/
0196 /**
0197  *
0198  * This function sets up the RX DMA operation on a 32bit Machine
0199  * For 64bit Dma transfers.
0200  *
0201  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0202  * @param   Msg is a pointer to the structure containing transfer data.
0203  *
0204  * @return  None
0205  *
0206  * @note    None.
0207  *
0208  ******************************************************************************/
0209 void XQspiPsu_Setup64BRxDma(const XQspiPsu *InstancePtr,
0210                     XQspiPsu_Msg *Msg)
0211 {
0212     s32 Remainder;
0213     s32 DmaRxBytes;
0214     u64 AddrTemp;
0215 
0216     Xil_AssertVoid(InstancePtr != NULL);
0217     Xil_AssertVoid(Msg != NULL);
0218     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0219 #ifdef DEBUG
0220     xil_printf("\nXQspiPsu_Setup64BRxDma\r\n");
0221 #endif
0222     AddrTemp = Msg->RxAddr64bit & XQSPIPSU_QSPIDMA_DST_ADDR_MASK;
0223 
0224     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0225             XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET, (u32)AddrTemp);
0226 
0227     AddrTemp = (Msg->RxAddr64bit >> 32);
0228     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0229             XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp &
0230             XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
0231 
0232     Remainder = InstancePtr->RxBytes % 4;
0233     DmaRxBytes = InstancePtr->RxBytes;
0234     if (Remainder != 0) {
0235         /* This is done to make Dma bytes aligned */
0236         DmaRxBytes = InstancePtr->RxBytes - Remainder;
0237         Msg->ByteCount = (u32)DmaRxBytes;
0238     }
0239 
0240     /* Write no. of words to DMA DST SIZE */
0241     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0242             XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
0243 
0244 }
0245 
0246 /*****************************************************************************/
0247 /**
0248  *
0249  * This function reads remaining bytes, after the completion of a DMA transfer,
0250  * using IO mode
0251  *
0252  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0253  * @param   Msg is a pointer to the structure containing transfer data.
0254  *
0255  * @return
0256  *      - XST_SUCCESS if successful.
0257  *      - XST_FAILURE if transfer fails.
0258  *      - XST_DEVICE_BUSY if a transfer is already in progress.
0259  *
0260  * @note    None.
0261  *
0262  ******************************************************************************/
0263 u32 XQspiPsu_SetIOMode(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
0264 {
0265     Xil_AssertNonvoid(InstancePtr != NULL);
0266     Xil_AssertNonvoid(Msg != NULL);
0267     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0268 #ifdef DEBUG
0269     xil_printf("\nXQspiPsu_DMARXComplete\r\n");
0270 #endif
0271 
0272     /* Read remaining bytes using IO mode */
0273     if ((InstancePtr->RxBytes % 4) != 0) {
0274         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,  XQSPIPSU_CFG_OFFSET,
0275                 (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) &
0276                         ~XQSPIPSU_CFG_MODE_EN_MASK));
0277         InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
0278         Msg->ByteCount = (u32)InstancePtr->RxBytes % 4U;
0279         Msg->RxBfrPtr += (InstancePtr->RxBytes - (InstancePtr->RxBytes % 4));
0280         InstancePtr->IsUnaligned = 1;
0281         return (u32) TRUE;
0282     }
0283     return (u32) FALSE;
0284 }
0285 
0286 /*****************************************************************************/
0287 /**
0288  *
0289  * This function checks the RX buffers in the message and setup the
0290  * RX DMA as required.
0291  *
0292  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0293  * @param   Msg is a pointer to the structure containing transfer data.
0294  *
0295  * @return  None
0296  *
0297  * @note    None.
0298  *
0299  ******************************************************************************/
0300 void XQspiPsu_RXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
0301 {
0302     Xil_AssertVoid(InstancePtr != NULL);
0303     Xil_AssertVoid(Msg != NULL);
0304     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0305 #ifdef DEBUG
0306     xil_printf("\nXQspiPsu_RXSetup\r\n");
0307 #endif
0308     InstancePtr->RxBytes = (s32)Msg->ByteCount;
0309 
0310     if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0311         if ((Msg->RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
0312             (Msg->Xfer64bit != (u8)0U)) {
0313             XQspiPsu_Setup64BRxDma(InstancePtr, Msg);
0314         } else {
0315             XQspiPsu_SetupRxDma(InstancePtr, Msg);
0316         }
0317     }
0318 }
0319 
0320 /*****************************************************************************/
0321 /**
0322  *
0323  * This function checks the TX/RX buffers in the message and setups up the
0324  * GENFIFO entries, TX FIFO or RX DMA as required.
0325  *
0326  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0327  * @param   Msg is a pointer to the structure containing transfer data.
0328  * @param   GenFifoEntry is pointer to the variable in which GENFIFO mask
0329  *      is returned to calling function
0330  *
0331  * @return  None
0332  *
0333  * @note    None.
0334  *
0335  ******************************************************************************/
0336 void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
0337                     u32 *GenFifoEntry)
0338 {
0339     Xil_AssertVoid(InstancePtr != NULL);
0340     Xil_AssertVoid(Msg != NULL);
0341     Xil_AssertVoid(GenFifoEntry != NULL);
0342     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0343 #ifdef DEBUG
0344     xil_printf("\nXQspiPsu_TXRXSetup\r\n");
0345 #endif
0346     /* Transmit */
0347     if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
0348             ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
0349 
0350         *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
0351         *GenFifoEntry |= XQSPIPSU_GENFIFO_TX;
0352         /* Discard RX data */
0353         *GenFifoEntry &= ~XQSPIPSU_GENFIFO_RX;
0354 
0355         /* Setup data to be TXed */
0356         XQspiPsu_TXSetup(InstancePtr, Msg);
0357 
0358         InstancePtr->RecvBufferPtr = NULL;
0359         InstancePtr->RxBytes = 0;
0360     }
0361     /*Receive*/
0362     if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE) &&
0363             ((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE)) {
0364 
0365         /* TX auto fill */
0366         *GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX;
0367         /* Setup RX */
0368         *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
0369         *GenFifoEntry |= XQSPIPSU_GENFIFO_RX;
0370 
0371         /* Setup DMA for data to be RXed */
0372         XQspiPsu_RXSetup(InstancePtr, Msg);
0373 
0374         InstancePtr->SendBufferPtr = NULL;
0375         InstancePtr->TxBytes = 0;
0376     }
0377     /* If only dummy is requested as a separate entry */
0378     if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE) &&
0379             ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
0380 
0381         *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
0382         *GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
0383         InstancePtr->TxBytes = 0;
0384         InstancePtr->RxBytes = 0;
0385         InstancePtr->SendBufferPtr = NULL;
0386         InstancePtr->RecvBufferPtr = NULL;
0387     }
0388     /* Dummy and cmd sent by upper layer to received data */
0389     if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
0390             ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
0391         *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
0392         *GenFifoEntry |= (XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
0393 
0394         /* Setup data to be TXed */
0395         XQspiPsu_TXSetup(InstancePtr, Msg);
0396         /* Setup DMA for data to be RXed */
0397         XQspiPsu_RXSetup(InstancePtr, Msg);
0398     }
0399 }
0400 /*****************************************************************************/
0401 /**
0402  *
0403  * This function writes the Data length to GENFIFO entries that need to be
0404  * transmitted or received.
0405  *
0406  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0407  * @param   Msg is a pointer to the structure containing transfer data.
0408  * @param   GenFifoEntry is index of the current message to be handled.
0409  *
0410  * @return
0411  *      - XST_SUCCESS if successful.
0412  *      - XST_FAILURE if transfer fails.
0413  *      - XST_DEVICE_BUSY if a transfer is already in progress.
0414  *
0415  * @note    None.
0416  *
0417  ******************************************************************************/
0418 void XQspiPsu_GenFifoEntryDataLen(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
0419         u32 *GenFifoEntry)
0420 {
0421     u32 TempCount;
0422     u32 ImmData;
0423 
0424     Xil_AssertVoid(InstancePtr != NULL);
0425     Xil_AssertVoid(Msg != NULL);
0426     Xil_AssertVoid(GenFifoEntry != NULL);
0427     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0428 #ifdef DEBUG
0429     xil_printf("\nXQspiPsu_GenFifoEntryDataLen\r\n");
0430 #endif
0431 
0432     if (Msg->ByteCount <= XQSPIPSU_GENFIFO_IMM_DATA_MASK) {
0433         *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
0434         *GenFifoEntry |= Msg->ByteCount;
0435     #ifdef DEBUG
0436     xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry);
0437     #endif
0438         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
0439                 *GenFifoEntry);
0440     } else {
0441         TempCount = Msg->ByteCount;
0442         u32 Exponent = 8;   /* 2^8 = 256 */
0443         ImmData = TempCount & 0xFFU;
0444         /* Exponent entries */
0445         *GenFifoEntry |= XQSPIPSU_GENFIFO_EXP;
0446         while (TempCount != 0U) {
0447             if ((TempCount & XQSPIPSU_GENFIFO_EXP_START) != (u32)FALSE) {
0448                 *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
0449                 *GenFifoEntry |= Exponent;
0450     #ifdef DEBUG
0451                 xil_printf("\nFifoEntry=%08x\r\n",
0452                     *GenFifoEntry);
0453     #endif
0454                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
0455                     *GenFifoEntry);
0456             }
0457             TempCount = TempCount >> 1;
0458             Exponent++;
0459         }
0460         /* Immediate entry */
0461         *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_EXP;
0462         if ((ImmData & 0xFFU) != (u32)FALSE) {
0463             *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
0464             *GenFifoEntry |= ImmData & 0xFFU;
0465     #ifdef DEBUG
0466             xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry);
0467     #endif
0468             XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
0469                     *GenFifoEntry);
0470         }
0471     }
0472 }
0473 
0474 /*****************************************************************************/
0475 /**
0476  *
0477  * This function creates Poll config register data to write
0478  *
0479  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0480  *
0481  * @param   FlashMsg is a pointer to the structure containing transfer data.
0482  *
0483  * @return  None
0484  *
0485  * @note    None.
0486  *
0487  ******************************************************************************/
0488 u32 XQspiPsu_CreatePollDataConfig(const XQspiPsu *InstancePtr,
0489         const XQspiPsu_Msg *FlashMsg)
0490 {
0491     u32 ConfigData = 0;
0492 
0493     Xil_AssertNonvoid(InstancePtr != NULL);
0494     Xil_AssertNonvoid(FlashMsg != NULL);
0495     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0496 #ifdef DEBUG
0497     xil_printf("\nXQspiPsu_CreatePollDataConfig\r\n");
0498 #endif
0499 
0500     if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_UPPER) != (u32)FALSE) {
0501         ConfigData = (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
0502                 XQSPIPSU_POLL_CFG_EN_MASK_UPPER_SHIFT;
0503     }
0504     if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_LOWER) != (u32)FALSE) {
0505         ConfigData |= (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
0506                 XQSPIPSU_POLL_CFG_EN_MASK_LOWER_SHIFT;
0507     }
0508     ConfigData |= (u32)(((u32)FlashMsg->PollBusMask <<
0509             XQSPIPSU_POLL_CFG_MASK_EN_SHIFT) & XQSPIPSU_POLL_CFG_MASK_EN_MASK);
0510     ConfigData |= (u32)(((u32)FlashMsg->PollData <<
0511             XQSPIPSU_POLL_CFG_DATA_VALUE_SHIFT)
0512             & XQSPIPSU_POLL_CFG_DATA_VALUE_MASK);
0513     return ConfigData;
0514 }
0515 
0516 /*****************************************************************************/
0517 /**
0518  *
0519  * Selects SPI mode - x1 or x2 or x4.
0520  *
0521  * @param   SpiMode - spi or dual or quad.
0522  * @return  Mask to set desired SPI mode in GENFIFO entry.
0523  *
0524  * @note    None.
0525  *
0526  ******************************************************************************/
0527 u32 XQspiPsu_SelectSpiMode(u8 SpiMode)
0528 {
0529     u32 Mask;
0530 
0531     Xil_AssertNonvoid(SpiMode > 0U);
0532 #ifdef DEBUG
0533     xil_printf("\nXQspiPsu_SelectSpiMode\r\n");
0534 #endif
0535 
0536     switch (SpiMode) {
0537     case XQSPIPSU_SELECT_MODE_DUALSPI:
0538         Mask = XQSPIPSU_GENFIFO_MODE_DUALSPI;
0539         break;
0540     case XQSPIPSU_SELECT_MODE_QUADSPI:
0541         Mask = XQSPIPSU_GENFIFO_MODE_QUADSPI;
0542         break;
0543     case XQSPIPSU_SELECT_MODE_SPI:
0544         Mask = XQSPIPSU_GENFIFO_MODE_SPI;
0545         break;
0546     default:
0547         Mask = XQSPIPSU_GENFIFO_MODE_SPI;
0548         break;
0549     }
0550 #ifdef DEBUG
0551     xil_printf("\nSPIMode is %08x\r\n", SpiMode);
0552 #endif
0553     return Mask;
0554 }
0555 
0556 /*****************************************************************************/
0557 /**
0558  *
0559  * Enable and initialize DMA Mode, set little endain, disable poll timeout,
0560  * clear prescalar bits and reset thresholds
0561  *
0562  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0563  *
0564  * @return  None.
0565  *
0566  * @note    None.
0567  *
0568  ******************************************************************************/
0569 void XQspiPsu_SetDefaultConfig(XQspiPsu *InstancePtr)
0570 {
0571     u32 ConfigReg;
0572 
0573     Xil_AssertVoid(InstancePtr != NULL);
0574 #ifdef DEBUG
0575     xil_printf("\nXQspiPsu_SetDefaultConfig\r\n");
0576 #endif
0577 
0578     /* Default value to config register */
0579     ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0580             XQSPIPSU_CFG_OFFSET);
0581 
0582     /* DMA mode */
0583     ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
0584     ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
0585     /* Manual start */
0586     ConfigReg |= XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK;
0587     /* Little endain by default */
0588     ConfigReg &= ~XQSPIPSU_CFG_ENDIAN_MASK;
0589     /* Disable poll timeout */
0590     ConfigReg &= ~XQSPIPSU_CFG_EN_POLL_TO_MASK;
0591     /* Set hold bit */
0592     ConfigReg |= XQSPIPSU_CFG_WP_HOLD_MASK;
0593     /* Clear prescalar by default */
0594     ConfigReg &= ~(u32)XQSPIPSU_CFG_BAUD_RATE_DIV_MASK;
0595     /* CPOL CPHA 00 */
0596     ConfigReg &= ~(u32)XQSPIPSU_CFG_CLK_PHA_MASK;
0597     ConfigReg &= ~(u32)XQSPIPSU_CFG_CLK_POL_MASK;
0598 
0599     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0600         XQSPIPSU_CFG_OFFSET, ConfigReg);
0601 
0602     /* Set by default to allow for high frequencies */
0603     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0604         XQSPIPSU_LPBK_DLY_ADJ_OFFSET,
0605         XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0606             XQSPIPSU_LPBK_DLY_ADJ_OFFSET) |
0607             XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK);
0608 
0609     /* Reset thresholds */
0610     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0611         XQSPIPSU_TX_THRESHOLD_OFFSET, XQSPIPSU_TX_FIFO_THRESHOLD_RESET_VAL);
0612     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0613         XQSPIPSU_RX_THRESHOLD_OFFSET, XQSPIPSU_RX_FIFO_THRESHOLD_RESET_VAL);
0614     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0615         XQSPIPSU_GF_THRESHOLD_OFFSET, XQSPIPSU_GEN_FIFO_THRESHOLD_RESET_VAL);
0616 
0617     /* DMA init */
0618     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0619             XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET,
0620             XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL);
0621 }
0622 
0623 /*****************************************************************************/
0624 /**
0625  *
0626  * Read the specified number of bytes from RX FIFO
0627  *
0628  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0629  * @param   Msg is a pointer to the structure containing transfer data.
0630  * @param   Size is the number of bytes to be read.
0631  *
0632  * @return  None
0633  *
0634  * @note    None.
0635  *
0636  ******************************************************************************/
0637 void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, s32 Size)
0638 {
0639     s32 Count = 0;
0640     u32 Data;
0641 
0642     Xil_AssertVoid(InstancePtr != NULL);
0643     Xil_AssertVoid(Msg != NULL);
0644     Xil_AssertVoid(Size > 0);
0645     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0646 #ifdef DEBUG
0647     xil_printf("\nXQspiPsu_ReadRxFifo\r\n");
0648 #endif
0649     while ((InstancePtr->RxBytes != 0) && (Count < Size)) {
0650         Data = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0651             XQSPIPSU_RXD_OFFSET);
0652 #ifdef DEBUG
0653         xil_printf("\nData is %08x\r\n", Data);
0654 #endif
0655         if (InstancePtr->RxBytes >= 4) {
0656             (void)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data, 4);
0657             InstancePtr->RxBytes -= 4;
0658             Msg->RxBfrPtr += 4;
0659             Count += 4;
0660         } else {
0661             /* Read unaligned bytes (< 4 bytes) */
0662             (void)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data,
0663                 (u32)InstancePtr->RxBytes);
0664             Msg->RxBfrPtr += InstancePtr->RxBytes;
0665             Count += InstancePtr->RxBytes;
0666             InstancePtr->RxBytes = 0;
0667         }
0668     }
0669 }
0670 
0671 /*****************************************************************************/
0672 /**
0673  *
0674  * This function reads data from RXFifo in IO mode.
0675  *
0676  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0677  * @param   Msg is a pointer to the structure containing transfer data.
0678  * @param   StatusReg is the Interrupt status Register value.
0679  *
0680  * @return  None.
0681  *
0682  * @note    None.
0683  *
0684  ******************************************************************************/
0685 void XQspiPsu_IORead(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
0686         u32 StatusReg)
0687 {
0688     s32 RxThr;
0689 
0690     Xil_AssertVoid(InstancePtr != NULL);
0691     Xil_AssertVoid(Msg != NULL);
0692     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0693 #ifdef DEBUG
0694     xil_printf("\nXQspiPsu_IORXComplete\r\n");
0695 #endif
0696 
0697     if ((StatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK) != 0U) {
0698             /*
0699              * Check if PIO RX is complete and
0700              * update RxBytes
0701              */
0702         RxThr = (s32)XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0703                 XQSPIPSU_RX_THRESHOLD_OFFSET);
0704         RxThr = RxThr*4;
0705         XQspiPsu_ReadRxFifo(InstancePtr, Msg, RxThr);
0706 
0707         return;
0708     }
0709 
0710     if ((StatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
0711         XQspiPsu_ReadRxFifo(InstancePtr, Msg, InstancePtr->RxBytes);
0712     }
0713 }
0714 
0715 #if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
0716 /*****************************************************************************/
0717 /**
0718 *
0719 * This function sets the Tapdelay values for the QSPIPSU device driver.The device
0720 * must be idle rather than busy transferring data before setting Tapdelay.
0721 *
0722 * @param    InstancePtr is a pointer to the XQspiPsu instance.
0723 * @param    TapdelayBypss contains the IOU_TAPDLY_BYPASS register value.
0724 * @param    LPBKDelay contains the GQSPI_LPBK_DLY_ADJ register value.
0725 * @param    Datadelay contains the QSPI_DATA_DLY_ADJ register value.
0726 *
0727 * @return
0728 *       - XST_SUCCESS if options are successfully set.
0729 *       - XST_DEVICE_BUSY if the device is currently transferring data.
0730 *       The transfer must complete or be aborted before setting TapDelay.
0731 *
0732 * @note
0733 * This function is not thread-safe.
0734 *
0735 ******************************************************************************/
0736 s32 XQspipsu_Set_TapDelay(const XQspiPsu *InstancePtr, u32 TapdelayBypass,
0737                         u32 LPBKDelay, u32 Datadelay)
0738 {
0739     s32 Status;
0740 
0741     Xil_AssertNonvoid(InstancePtr != NULL);
0742     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0743 
0744     /*
0745      * Do not allow to modify the Control Register while a transfer is in
0746      * progress. Not thread-safe.
0747      */
0748     if (InstancePtr->IsBusy == (u32)TRUE) {
0749         Status = (s32)XST_DEVICE_BUSY;
0750     } else {
0751 #if defined (__aarch64__) && (EL1_NONSECURE == 1) && !defined (versal)
0752         Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(XPS_SYS_CTRL_BASEADDR +
0753                 IOU_TAPDLY_BYPASS_OFFSET) | ((u64)(0x4) << 32),
0754                 (u64)TapdelayBypass, 0, 0, 0, 0, 0);
0755 #elif defined (versal)
0756         XQspiPsu_WriteReg(XQSPIPS_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET,
0757                 TapdelayBypass);
0758 #else
0759         XQspiPsu_WriteReg(XPS_SYS_CTRL_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET,
0760                 TapdelayBypass);
0761 #endif
0762         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0763                 XQSPIPSU_LPBK_DLY_ADJ_OFFSET, LPBKDelay);
0764         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0765                 XQSPIPSU_DATA_DLY_ADJ_OFFSET, Datadelay);
0766 
0767         Status = (s32)XST_SUCCESS;
0768     }
0769     return Status;
0770 }
0771 #endif
0772 /** @} */