1 /******************************************************************************
3 * Copyright (C) 2014 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
36 * @addtogroup qspipsu_v1_0
39 * This file implements the functions required to use the QSPIPSU hardware to
40 * perform a transfer. These are accessible to the user via xqspipsu.h.
43 * MODIFICATION HISTORY:
45 * Ver Who Date Changes
46 * ----- --- -------- -----------------------------------------------
47 * 1.0 hk 08/21/14 First release
48 * sk 03/13/15 Added IO mode support.
49 * hk 03/18/15 Switch to I/O mode before clearing RX FIFO.
50 * Clear and disbale DMA interrupts/status in abort.
51 * Use DMA DONE bit instead of BUSY as recommended.
52 * sk 04/24/15 Modified the code according to MISRAC-2012.
53 * sk 06/17/15 Removed NULL checks for Rx/Tx buffers. As
54 * writing/reading from 0x0 location is permitted.
58 ******************************************************************************/
60 /***************************** Include Files *********************************/
64 /************************** Constant Definitions *****************************/
66 /**************************** Type Definitions *******************************/
68 /***************** Macros (Inline Functions) Definitions *********************/
70 /************************** Function Prototypes ******************************/
71 static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
73 static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode);
74 static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
76 static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
77 XQspiPsu_Msg *Msg, s32 Size);
78 static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
80 static inline void XQspiPsu_GenFifoEntryCSAssert(XQspiPsu *InstancePtr);
81 static inline void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr,
82 XQspiPsu_Msg *Msg, s32 Index);
83 static inline void XQspiPsu_GenFifoEntryCSDeAssert(XQspiPsu *InstancePtr);
84 static inline void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,
85 XQspiPsu_Msg *Msg, s32 Size);
87 /************************** Variable Definitions *****************************/
89 /*****************************************************************************/
92 * Initializes a specific XQspiPsu instance such that the driver is ready to use.
95 * @param InstancePtr is a pointer to the XQspiPsu instance.
96 * @param ConfigPtr is a reference to a structure containing information
97 * about a specific QSPIPSU device. This function initializes an
98 * InstancePtr object for a specific device specified by the
100 * @param EffectiveAddr is the device base address in the virtual memory
101 * address space. The caller is responsible for keeping the address
102 * mapping from EffectiveAddr to the device physical base address
103 * unchanged once this function is invoked. Unexpected errors may
104 * occur if the address mapping changes after this function is
105 * called. If address translation is not used, use
106 * ConfigPtr->Config.BaseAddress for this device.
109 * - XST_SUCCESS if successful.
110 * - XST_DEVICE_IS_STARTED if the device is already started.
111 * It must be stopped to re-initialize.
115 ******************************************************************************/
116 s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr, XQspiPsu_Config *ConfigPtr,
119 Xil_AssertNonvoid(InstancePtr != NULL);
120 Xil_AssertNonvoid(ConfigPtr != NULL);
124 * If the device is busy, disallow the initialize and return a status
125 * indicating it is already started. This allows the user to stop the
126 * device and re-initialize, but prevents a user from inadvertently
127 * initializing. This assumes the busy flag is cleared at startup.
129 if (InstancePtr->IsBusy == TRUE) {
130 Status = (s32)XST_DEVICE_IS_STARTED;
133 /* Set some default values. */
134 InstancePtr->IsBusy = FALSE;
136 InstancePtr->Config.BaseAddress = EffectiveAddr + XQSPIPSU_OFFSET;
137 InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode;
138 InstancePtr->StatusHandler = StubStatusHandler;
139 InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
141 /* Other instance variable initializations */
142 InstancePtr->SendBufferPtr = NULL;
143 InstancePtr->RecvBufferPtr = NULL;
144 InstancePtr->GenFifoBufferPtr = NULL;
145 InstancePtr->TxBytes = 0;
146 InstancePtr->RxBytes = 0;
147 InstancePtr->GenFifoEntries = 0;
148 InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
149 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
150 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
151 InstancePtr->IsUnaligned = 0;
152 InstancePtr->IsManualstart = TRUE;
155 XQspiPsu_Select(InstancePtr);
158 * Reset the QSPIPSU device to get it into its initial state. It is
159 * expected that device configuration will take place after this
160 * initialization is done, but before the device is started.
162 XQspiPsu_Reset(InstancePtr);
164 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
166 Status = XST_SUCCESS;
172 /*****************************************************************************/
175 * Resets the QSPIPSU device. Reset must only be called after the driver has
176 * been initialized. Any data transfer that is in progress is aborted.
178 * The upper layer software is responsible for re-configuring (if necessary)
179 * and restarting the QSPIPSU device after the reset.
181 * @param InstancePtr is a pointer to the XQspiPsu instance.
187 ******************************************************************************/
188 void XQspiPsu_Reset(XQspiPsu *InstancePtr)
192 Xil_AssertVoid(InstancePtr != NULL);
194 /* Abort any transfer that is in progress */
195 XQspiPsu_Abort(InstancePtr);
197 /* Default value to config register */
198 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
199 XQSPIPSU_CFG_OFFSET);
202 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
203 ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
205 ConfigReg |= XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK;
206 /* Little endain by default */
207 ConfigReg &= ~XQSPIPSU_CFG_ENDIAN_MASK;
208 /* Disable poll timeout */
209 ConfigReg &= ~XQSPIPSU_CFG_EN_POLL_TO_MASK;
211 ConfigReg |= XQSPIPSU_CFG_WP_HOLD_MASK;
212 /* Clear prescalar by default */
213 ConfigReg &= (u32)(~XQSPIPSU_CFG_BAUD_RATE_DIV_MASK);
215 ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_PHA_MASK);
216 ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_POL_MASK);
218 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
219 XQSPIPSU_CFG_OFFSET, ConfigReg);
221 /* Set by default to allow for high frequencies */
222 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
223 XQSPIPSU_LPBK_DLY_ADJ_OFFSET,
224 XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
225 XQSPIPSU_LPBK_DLY_ADJ_OFFSET) |
226 XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK);
228 /* Reset thresholds */
229 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
230 XQSPIPSU_TX_THRESHOLD_OFFSET,
231 XQSPIPSU_TX_FIFO_THRESHOLD_RESET_VAL);
232 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
233 XQSPIPSU_RX_THRESHOLD_OFFSET,
234 XQSPIPSU_RX_FIFO_THRESHOLD_RESET_VAL);
235 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
236 XQSPIPSU_GF_THRESHOLD_OFFSET,
237 XQSPIPSU_GEN_FIFO_THRESHOLD_RESET_VAL);
240 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
241 XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET,
242 XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL);
246 /*****************************************************************************/
249 * Aborts a transfer in progress by
251 * @param InstancePtr is a pointer to the XQspiPsu instance.
257 ******************************************************************************/
258 void XQspiPsu_Abort(XQspiPsu *InstancePtr)
261 u32 IntrStatus, ConfigReg;
263 IntrStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
264 XQSPIPSU_ISR_OFFSET);
266 /* Clear and disable interrupts */
267 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
268 XQSPIPSU_ISR_OFFSET, IntrStatus | XQSPIPSU_ISR_WR_TO_CLR_MASK);
269 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
270 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
271 XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
272 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET));
273 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
274 XQSPIPSU_QSPIDMA_DST_STS_OFFSET,
275 XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
276 XQSPIPSU_QSPIDMA_DST_STS_OFFSET) |
277 XQSPIPSU_QSPIDMA_DST_STS_WTC);
278 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
279 XQSPIPSU_IDR_OFFSET, XQSPIPSU_IDR_ALL_MASK);
280 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
281 XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
282 XQSPIPSU_QSPIDMA_DST_INTR_ALL_MASK);
285 if((XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
286 XQSPIPSU_ISR_OFFSET) & XQSPIPSU_ISR_RXEMPTY_MASK) != FALSE) {
287 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
288 XQSPIPSU_FIFO_CTRL_OFFSET,
289 XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_MASK |
290 XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_MASK);
294 * Switch to IO mode to Clear RX FIFO. This is becuase of DMA behaviour
295 * where it waits on RX empty and goes busy assuming there is data
296 * to be transfered even if there is no request.
298 if ((IntrStatus & XQSPIPSU_ISR_RXEMPTY_MASK) != 0U) {
299 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
300 XQSPIPSU_CFG_OFFSET);
301 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
302 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
303 XQSPIPSU_CFG_OFFSET, ConfigReg);
305 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
306 XQSPIPSU_FIFO_CTRL_OFFSET,
307 XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK);
309 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
310 ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
311 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
312 XQSPIPSU_CFG_OFFSET, ConfigReg);
316 /* Disable QSPIPSU */
317 XQspiPsu_Disable(InstancePtr);
319 InstancePtr->TxBytes = 0;
320 InstancePtr->RxBytes = 0;
321 InstancePtr->GenFifoEntries = 0;
322 InstancePtr->IsBusy = FALSE;
325 /*****************************************************************************/
328 * This function performs a transfer on the bus in polled mode. The messages
329 * passed are all transferred on the bus between one CS assert and de-assert.
331 * @param InstancePtr is a pointer to the XQspiPsu instance.
332 * @param Msg is a pointer to the structure containing transfer data.
333 * @param NumMsg is the number of messages to be transferred.
336 * - XST_SUCCESS if successful.
337 * - XST_FAILURE if transfer fails.
338 * - XST_DEVICE_BUSY if a transfer is already in progress.
342 ******************************************************************************/
343 s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
349 u32 QspiPsuStatusReg, DmaStatusReg;
353 u32 IOPending = (u32)FALSE;
355 Xil_AssertNonvoid(InstancePtr != NULL);
356 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
357 for (Index = 0; Index < (s32)NumMsg; Index++) {
358 Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
361 /* Check whether there is another transfer in progress. Not thread-safe */
362 if (InstancePtr->IsBusy == TRUE) {
363 return (s32)XST_DEVICE_BUSY;
366 /* Check for ByteCount upper limit - 2^28 for DMA */
367 for (Index = 0; Index < (s32)NumMsg; Index++) {
368 if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
369 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
370 return (s32)XST_FAILURE;
375 * Set the busy flag, which will be cleared when the transfer is
378 InstancePtr->IsBusy = TRUE;
380 BaseAddress = InstancePtr->Config.BaseAddress;
383 XQspiPsu_Enable(InstancePtr);
386 XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
390 while (Index < (s32)NumMsg) {
391 XQspiPsu_GenFifoEntryData(InstancePtr, Msg, Index);
393 if (InstancePtr->IsManualstart == TRUE) {
394 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
395 XQspiPsu_ReadReg(BaseAddress,
396 XQSPIPSU_CFG_OFFSET) |
397 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
400 /* Use thresholds here */
401 /* If there is more data to be transmitted */
403 QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
404 XQSPIPSU_ISR_OFFSET);
406 /* Transmit more data if left */
407 if (((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
408 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
409 (InstancePtr->TxBytes > 0)) {
410 XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
414 /* Check if DMA RX is complete and update RxBytes */
415 if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
416 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
418 DmaIntrSts = XQspiPsu_ReadReg(BaseAddress,
419 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
420 if ((DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
421 XQspiPsu_WriteReg(BaseAddress,
422 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
424 /* Read remaining bytes using IO mode */
425 if((InstancePtr->RxBytes % 4) != 0 ) {
426 XQspiPsu_WriteReg(BaseAddress,
428 (XQspiPsu_ReadReg(BaseAddress,
429 XQSPIPSU_CFG_OFFSET) &
430 ~XQSPIPSU_CFG_MODE_EN_MASK));
431 InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
432 Msg[Index].ByteCount =
433 (InstancePtr->RxBytes % 4);
434 Msg[Index].RxBfrPtr += (InstancePtr->RxBytes -
435 (InstancePtr->RxBytes % 4));
436 InstancePtr->IsUnaligned = 1;
437 IOPending = (u32)TRUE;
440 InstancePtr->RxBytes = 0;
443 if ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) {
444 /* Check if PIO RX is complete and update RxBytes */
445 RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
446 XQSPIPSU_RX_THRESHOLD_OFFSET);
447 if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
449 XQspiPsu_ReadRxFifo(InstancePtr,
450 &Msg[Index], RxThr*4);
453 if ((QspiPsuStatusReg &
454 XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
455 XQspiPsu_ReadRxFifo(InstancePtr,
456 &Msg[Index], InstancePtr->RxBytes);
461 } while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) ||
462 (InstancePtr->TxBytes != 0) ||
463 ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == FALSE) ||
464 (InstancePtr->RxBytes != 0));
466 if((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
467 InstancePtr->IsUnaligned = 0;
468 XQspiPsu_WriteReg(BaseAddress,
469 XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
471 XQSPIPSU_CFG_OFFSET) |
472 XQSPIPSU_CFG_MODE_EN_DMA_MASK));
473 InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
476 if (IOPending == (u32)TRUE) {
477 IOPending = (u32)FALSE;
483 /* De-select slave */
484 XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
486 if (InstancePtr->IsManualstart == TRUE) {
487 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
488 XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
489 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
492 QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
493 while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) {
494 QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
495 XQSPIPSU_ISR_OFFSET);
498 /* Clear the busy flag. */
499 InstancePtr->IsBusy = FALSE;
501 /* Disable the device. */
502 XQspiPsu_Disable(InstancePtr);
507 /*****************************************************************************/
510 * This function initiates a transfer on the bus and enables interrupts.
511 * The transfer is completed by the interrupt handler. The messages passed are
512 * all transferred on the bus between one CS assert and de-assert.
514 * @param InstancePtr is a pointer to the XQspiPsu instance.
515 * @param Msg is a pointer to the structure containing transfer data.
516 * @param NumMsg is the number of messages to be transferred.
519 * - XST_SUCCESS if successful.
520 * - XST_FAILURE if transfer fails.
521 * - XST_DEVICE_BUSY if a transfer is already in progress.
525 ******************************************************************************/
526 s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
535 Xil_AssertNonvoid(InstancePtr != NULL);
536 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
537 for (Index = 0; Index < (s32)NumMsg; Index++) {
538 Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
541 /* Check whether there is another transfer in progress. Not thread-safe */
542 if (InstancePtr->IsBusy == TRUE) {
543 return (s32)XST_DEVICE_BUSY;
546 /* Check for ByteCount upper limit - 2^28 for DMA */
547 for (Index = 0; Index < (s32)NumMsg; Index++) {
548 if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
549 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
550 return (s32)XST_FAILURE;
555 * Set the busy flag, which will be cleared when the transfer is
558 InstancePtr->IsBusy = TRUE;
560 BaseAddress = InstancePtr->Config.BaseAddress;
562 InstancePtr->Msg = Msg;
563 InstancePtr->NumMsg = (s32)NumMsg;
564 InstancePtr->MsgCnt = 0;
567 XQspiPsu_Enable(InstancePtr);
570 XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
572 /* This might not work if not manual start */
573 /* Put first message in FIFO along with the above slave select */
574 XQspiPsu_GenFifoEntryData(InstancePtr, Msg, 0);
576 if (InstancePtr->IsManualstart == TRUE) {
577 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
578 XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
579 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
582 /* Enable interrupts */
583 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IER_OFFSET,
584 (u32)XQSPIPSU_IER_TXNOT_FULL_MASK | (u32)XQSPIPSU_IER_TXEMPTY_MASK |
585 (u32)XQSPIPSU_IER_RXNEMPTY_MASK | (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
586 (u32)XQSPIPSU_IER_RXEMPTY_MASK);
588 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
589 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
590 XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
596 /*****************************************************************************/
599 * Handles interrupt based transfers by acting on GENFIFO and DMA interurpts.
601 * @param InstancePtr is a pointer to the XQspiPsu instance.
604 * - XST_SUCCESS if successful.
605 * - XST_FAILURE if transfer fails.
609 ******************************************************************************/
610 s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr)
612 u32 QspiPsuStatusReg, DmaIntrStatusReg = 0;
621 Xil_AssertNonvoid(InstancePtr != NULL);
623 BaseAddress = InstancePtr->Config.BaseAddress;
624 Msg = InstancePtr->Msg;
625 NumMsg = InstancePtr->NumMsg;
626 MsgCnt = InstancePtr->MsgCnt;
627 TxRxFlag = Msg[MsgCnt].Flags;
629 /* QSPIPSU Intr cleared on read */
630 QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
631 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
632 /* DMA Intr write to clear */
633 DmaIntrStatusReg = XQspiPsu_ReadReg(BaseAddress,
634 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
636 XQspiPsu_WriteReg(BaseAddress,
637 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrStatusReg);
639 if (((QspiPsuStatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK) != FALSE) ||
640 ((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK) != FALSE)) {
641 /* Call status handler to indicate error */
642 InstancePtr->StatusHandler(InstancePtr->StatusRef,
643 XST_SPI_COMMAND_ERROR, 0);
646 /* Fill more data to be txed if required */
647 if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
648 ((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
649 (InstancePtr->TxBytes > 0)) {
650 XQspiPsu_FillTxFifo(InstancePtr, &Msg[MsgCnt],
655 * Check if the entry is ONLY TX and increase MsgCnt.
656 * This is to allow TX and RX together in one entry - corner case.
658 if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
659 ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) != FALSE) &&
660 ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
661 (InstancePtr->TxBytes == 0) &&
662 ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE)) {
667 if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
668 (MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
669 if ((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
670 /* Read remaining bytes using IO mode */
671 if((InstancePtr->RxBytes % 4) != 0 ) {
672 XQspiPsu_WriteReg(BaseAddress,
673 XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
674 BaseAddress, XQSPIPSU_CFG_OFFSET) &
675 ~XQSPIPSU_CFG_MODE_EN_MASK));
676 InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
677 Msg[MsgCnt].ByteCount = (InstancePtr->RxBytes % 4);
678 Msg[MsgCnt].RxBfrPtr += (InstancePtr->RxBytes -
679 (InstancePtr->RxBytes % 4));
680 InstancePtr->IsUnaligned = 1;
681 XQspiPsu_GenFifoEntryData(InstancePtr, Msg,
683 if(InstancePtr->IsManualstart == TRUE) {
684 XQspiPsu_WriteReg(BaseAddress,
686 XQspiPsu_ReadReg(BaseAddress,
687 XQSPIPSU_CFG_OFFSET) |
688 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
692 InstancePtr->RxBytes = 0;
698 if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
699 if (InstancePtr->RxBytes != 0) {
700 if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
702 RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
703 XQSPIPSU_RX_THRESHOLD_OFFSET);
704 XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
707 if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
708 ((QspiPsuStatusReg & XQSPIPSU_ISR_RXEMPTY_MASK) == FALSE)) {
709 XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
710 InstancePtr->RxBytes);
713 if (InstancePtr->RxBytes == 0) {
722 * Dummy byte transfer
723 * MsgCnt < NumMsg check is to ensure is it a valid dummy cycle message
724 * If one of the above conditions increased MsgCnt, then
725 * the new message is yet to be placed in the FIFO; hence !DeltaMsgCnt.
727 if ((MsgCnt < NumMsg) && (DeltaMsgCnt == FALSE) &&
728 ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE) &&
729 ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) == FALSE) &&
730 ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE)) {
734 InstancePtr->MsgCnt = MsgCnt;
737 * DeltaMsgCnt is to handle conditions where genfifo empty can be set
738 * while tx is still not empty or rx dma is not yet done.
739 * MsgCnt > NumMsg indicates CS de-assert entry was also executed.
741 if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
742 ((DeltaMsgCnt != FALSE) || (MsgCnt > NumMsg))) {
743 if (MsgCnt < NumMsg) {
744 if(InstancePtr->IsUnaligned != 0) {
745 InstancePtr->IsUnaligned = 0;
746 XQspiPsu_WriteReg(InstancePtr->Config.
747 BaseAddress, XQSPIPSU_CFG_OFFSET,
748 (XQspiPsu_ReadReg(InstancePtr->Config.
749 BaseAddress, XQSPIPSU_CFG_OFFSET) |
750 XQSPIPSU_CFG_MODE_EN_DMA_MASK));
751 InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
753 /* This might not work if not manual start */
754 XQspiPsu_GenFifoEntryData(InstancePtr, Msg, MsgCnt);
756 if (InstancePtr->IsManualstart == TRUE) {
757 XQspiPsu_WriteReg(BaseAddress,
759 XQspiPsu_ReadReg(BaseAddress,
760 XQSPIPSU_CFG_OFFSET) |
761 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
763 } else if (MsgCnt == NumMsg) {
764 /* This is just to keep track of the de-assert entry */
766 InstancePtr->MsgCnt = MsgCnt;
768 /* De-select slave */
769 XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
771 if (InstancePtr->IsManualstart == TRUE) {
772 XQspiPsu_WriteReg(BaseAddress,
774 XQspiPsu_ReadReg(BaseAddress,
775 XQSPIPSU_CFG_OFFSET) |
776 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
779 /* Disable interrupts */
780 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IDR_OFFSET,
781 (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
782 (u32)XQSPIPSU_IER_TXEMPTY_MASK |
783 (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
784 (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
785 (u32)XQSPIPSU_IER_RXEMPTY_MASK);
786 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
787 XQspiPsu_WriteReg(BaseAddress,
788 XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
789 XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
792 /* Clear the busy flag. */
793 InstancePtr->IsBusy = FALSE;
795 /* Disable the device. */
796 XQspiPsu_Disable(InstancePtr);
798 /* Call status handler to indicate completion */
799 InstancePtr->StatusHandler(InstancePtr->StatusRef,
800 XST_SPI_TRANSFER_DONE, 0);
807 /*****************************************************************************/
810 * Sets the status callback function, the status handler, which the driver
811 * calls when it encounters conditions that should be reported to upper
812 * layer software. The handler executes in an interrupt context, so it must
813 * minimize the amount of processing performed. One of the following status
814 * events is passed to the status handler.
818 * XST_SPI_TRANSFER_DONE The requested data transfer is done
820 * XST_SPI_TRANSMIT_UNDERRUN As a slave device, the master clocked data
821 * but there were none available in the transmit
822 * register/FIFO. This typically means the slave
823 * application did not issue a transfer request
824 * fast enough, or the processor/driver could not
825 * fill the transmit register/FIFO fast enough.
827 * XST_SPI_RECEIVE_OVERRUN The QSPIPSU device lost data. Data was received
828 * but the receive data register/FIFO was full.
831 * @param InstancePtr is a pointer to the XQspiPsu instance.
832 * @param CallBackRef is the upper layer callback reference passed back
833 * when the callback function is invoked.
834 * @param FuncPointer is the pointer to the callback function.
840 * The handler is called within interrupt context, so it should do its work
841 * quickly and queue potentially time-consuming work to a task-level thread.
843 ******************************************************************************/
844 void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
845 XQspiPsu_StatusHandler FuncPointer)
847 Xil_AssertVoid(InstancePtr != NULL);
848 Xil_AssertVoid(FuncPointer != NULL);
849 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
851 InstancePtr->StatusHandler = FuncPointer;
852 InstancePtr->StatusRef = CallBackRef;
855 /*****************************************************************************/
858 * This is a stub for the status callback. The stub is here in case the upper
859 * layers forget to set the handler.
861 * @param CallBackRef is a pointer to the upper layer callback reference
862 * @param StatusEvent is the event that just occurred.
863 * @param ByteCount is the number of bytes transferred up until the event
870 ******************************************************************************/
871 static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
874 (void *) CallBackRef;
878 Xil_AssertVoidAlways();
881 /*****************************************************************************/
884 * Selects SPI mode - x1 or x2 or x4.
886 * @param SpiMode - spi or dual or quad.
887 * @return Mask to set desired SPI mode in GENFIFO entry.
891 ******************************************************************************/
892 static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode)
896 case XQSPIPSU_SELECT_MODE_DUALSPI:
897 Mask = XQSPIPSU_GENFIFO_MODE_DUALSPI;
899 case XQSPIPSU_SELECT_MODE_QUADSPI:
900 Mask = XQSPIPSU_GENFIFO_MODE_QUADSPI;
902 case XQSPIPSU_SELECT_MODE_SPI:
903 Mask = XQSPIPSU_GENFIFO_MODE_SPI;
906 Mask = XQSPIPSU_GENFIFO_MODE_SPI;
913 /*****************************************************************************/
916 * This function checks the TX/RX buffers in the message and setups up the
917 * GENFIFO entries, TX FIFO or RX DMA as required.
919 * @param InstancePtr is a pointer to the XQspiPsu instance.
920 * @param Msg is a pointer to the structure containing transfer data.
921 * @param GenFifoEntry is pointer to the variable in which GENFIFO mask
922 * is returned to calling function
928 ******************************************************************************/
929 static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
932 Xil_AssertVoid(InstancePtr != NULL);
935 if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
936 ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == FALSE)) {
937 /* Setup data to be TXed */
938 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
939 *GenFifoEntry |= XQSPIPSU_GENFIFO_TX;
940 InstancePtr->TxBytes = (s32)Msg->ByteCount;
941 InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
942 InstancePtr->RecvBufferPtr = NULL;
943 XQspiPsu_FillTxFifo(InstancePtr, Msg, XQSPIPSU_TXD_DEPTH);
944 /* Discard RX data */
945 *GenFifoEntry &= ~XQSPIPSU_GENFIFO_RX;
946 InstancePtr->RxBytes = 0;
950 if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) &&
951 ((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == FALSE)) {
953 *GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX;
954 InstancePtr->TxBytes = 0;
956 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
957 *GenFifoEntry |= XQSPIPSU_GENFIFO_RX;
958 InstancePtr->RxBytes = (s32)Msg->ByteCount;
959 InstancePtr->SendBufferPtr = NULL;
960 InstancePtr->RecvBufferPtr = Msg->RxBfrPtr;
961 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
962 XQspiPsu_SetupRxDma(InstancePtr, Msg);
966 /* If only dummy is requested as a separate entry */
967 if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == FALSE) &&
968 (Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == FALSE) {
969 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
970 *GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
971 InstancePtr->TxBytes = 0;
972 InstancePtr->RxBytes = 0;
973 InstancePtr->SendBufferPtr = NULL;
974 InstancePtr->RecvBufferPtr = NULL;
977 /* Dummy and cmd sent by upper layer to received data */
978 if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
979 ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
980 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
981 *GenFifoEntry |= (XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
982 InstancePtr->TxBytes = (s32)Msg->ByteCount;
983 InstancePtr->RxBytes = (s32)Msg->ByteCount;
984 InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
985 InstancePtr->RecvBufferPtr = Msg->RxBfrPtr;
986 XQspiPsu_FillTxFifo(InstancePtr, Msg, XQSPIPSU_TXD_DEPTH);
987 /* Add check for DMA or PIO here */
988 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
989 XQspiPsu_SetupRxDma(InstancePtr, Msg);
994 /*****************************************************************************/
997 * Fills the TX FIFO as long as there is room in the FIFO or the bytes required
1000 * @param InstancePtr is a pointer to the XQspiPsu instance.
1001 * @param Msg is a pointer to the structure containing transfer data.
1002 * @param Size is the number of bytes to be transmitted.
1008 ******************************************************************************/
1009 static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
1010 XQspiPsu_Msg *Msg, s32 Size)
1015 Xil_AssertVoid(InstancePtr != NULL);
1017 while ((InstancePtr->TxBytes > 0) && (Count < Size)) {
1018 if (InstancePtr->TxBytes >= 4) {
1019 (void)memcpy(&Data, Msg->TxBfrPtr, 4);
1021 InstancePtr->TxBytes -= 4;
1024 (void)memcpy(&Data, Msg->TxBfrPtr, InstancePtr->TxBytes);
1025 Msg->TxBfrPtr += InstancePtr->TxBytes;
1026 Count += InstancePtr->TxBytes;
1027 InstancePtr->TxBytes = 0;
1029 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1030 XQSPIPSU_TXD_OFFSET, Data);
1033 if (InstancePtr->TxBytes < 0) {
1034 InstancePtr->TxBytes = 0;
1038 /*****************************************************************************/
1041 * This function sets up the RX DMA operation.
1043 * @param InstancePtr is a pointer to the XQspiPsu instance.
1044 * @param Msg is a pointer to the structure containing transfer data.
1050 ******************************************************************************/
1051 static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
1058 Xil_AssertVoid(InstancePtr != NULL);
1060 AddrTemp = (u64)((INTPTR)(Msg->RxBfrPtr) &
1061 XQSPIPSU_QSPIDMA_DST_ADDR_MASK);
1062 /* Check for RXBfrPtr to be word aligned */
1063 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1064 XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET,
1067 AddrTemp = AddrTemp >> 32;
1068 if ((AddrTemp & 0xFFFU) != FALSE) {
1069 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1070 XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET,
1072 XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
1075 Remainder = InstancePtr->RxBytes % 4;
1076 DmaRxBytes = InstancePtr->RxBytes;
1077 if (Remainder != 0) {
1078 /* This is done to make Dma bytes aligned */
1079 DmaRxBytes = InstancePtr->RxBytes - Remainder;
1080 Msg->ByteCount = (u32)DmaRxBytes;
1083 Xil_DCacheInvalidateRange((INTPTR)InstancePtr->RecvBufferPtr, Msg->ByteCount);
1085 /* Write no. of words to DMA DST SIZE */
1086 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1087 XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
1091 /*****************************************************************************/
1094 * This function writes the GENFIFO entry to assert CS.
1096 * @param InstancePtr is a pointer to the XQspiPsu instance.
1102 ******************************************************************************/
1103 static inline void XQspiPsu_GenFifoEntryCSAssert(XQspiPsu *InstancePtr)
1107 GenFifoEntry = 0x0U;
1108 GenFifoEntry &= ~((u32)XQSPIPSU_GENFIFO_DATA_XFER | (u32)XQSPIPSU_GENFIFO_EXP);
1109 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
1110 GenFifoEntry |= XQSPIPSU_GENFIFO_MODE_SPI;
1111 GenFifoEntry |= InstancePtr->GenFifoCS;
1112 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
1113 GenFifoEntry |= InstancePtr->GenFifoBus;
1114 GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX |
1115 XQSPIPSU_GENFIFO_STRIPE | XQSPIPSU_GENFIFO_POLL);
1116 GenFifoEntry |= XQSPIPSU_GENFIFO_CS_SETUP;
1118 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1119 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1122 /*****************************************************************************/
1125 * This function writes the GENFIFO entries to transmit the messages requested.
1127 * @param InstancePtr is a pointer to the XQspiPsu instance.
1128 * @param Msg is a pointer to the structure containing transfer data.
1129 * @param Index of the current message to be handled.
1132 * - XST_SUCCESS if successful.
1133 * - XST_FAILURE if transfer fails.
1134 * - XST_DEVICE_BUSY if a transfer is already in progress.
1138 ******************************************************************************/
1139 static inline void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr,
1140 XQspiPsu_Msg *Msg, s32 Index)
1147 BaseAddress = InstancePtr->Config.BaseAddress;
1149 GenFifoEntry = 0x0U;
1151 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
1152 GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg[Index].BusWidth);
1154 GenFifoEntry |= InstancePtr->GenFifoCS;
1155 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
1156 GenFifoEntry |= InstancePtr->GenFifoBus;
1159 if (((Msg[Index].Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != FALSE) {
1160 GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
1162 GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
1165 /* If Byte Count is less than 8 bytes do the transfer in IO mode */
1166 if ((Msg[Index].ByteCount < 8U) &&
1167 (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA)) {
1168 InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
1169 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
1170 (XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) &
1171 ~XQSPIPSU_CFG_MODE_EN_MASK));
1172 InstancePtr->IsUnaligned = 1;
1175 XQspiPsu_TXRXSetup(InstancePtr, &Msg[Index], &GenFifoEntry);
1177 if (Msg[Index].ByteCount < XQSPIPSU_GENFIFO_IMM_DATA_MASK) {
1178 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
1179 GenFifoEntry |= Msg[Index].ByteCount;
1180 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
1183 TempCount = Msg[Index].ByteCount;
1184 u32 Exponent = 8; /* 2^8 = 256 */
1186 ImmData = TempCount & 0xFFU;
1187 /* Exponent entries */
1188 GenFifoEntry |= XQSPIPSU_GENFIFO_EXP;
1189 while (TempCount != 0U) {
1190 if ((TempCount & XQSPIPSU_GENFIFO_EXP_START) != FALSE) {
1191 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
1192 GenFifoEntry |= Exponent;
1193 XQspiPsu_WriteReg(BaseAddress,
1194 XQSPIPSU_GEN_FIFO_OFFSET,
1197 TempCount = TempCount >> 1;
1201 /* Immediate entry */
1202 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_EXP);
1203 if ((ImmData & 0xFFU) != FALSE) {
1204 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
1205 GenFifoEntry |= ImmData & 0xFFU;
1206 XQspiPsu_WriteReg(BaseAddress,
1207 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1211 /* One dummy GenFifo entry in case of IO mode */
1212 if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) &&
1213 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
1214 GenFifoEntry = 0x0U;
1215 XQspiPsu_WriteReg(BaseAddress,
1216 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1220 /*****************************************************************************/
1223 * This function writes the GENFIFO entry to de-assert CS.
1225 * @param InstancePtr is a pointer to the XQspiPsu instance.
1231 ******************************************************************************/
1232 static inline void XQspiPsu_GenFifoEntryCSDeAssert(XQspiPsu *InstancePtr)
1236 GenFifoEntry = 0x0U;
1237 GenFifoEntry &= ~((u32)XQSPIPSU_GENFIFO_DATA_XFER | (u32)XQSPIPSU_GENFIFO_EXP);
1238 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
1239 GenFifoEntry |= XQSPIPSU_GENFIFO_MODE_SPI;
1240 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
1241 GenFifoEntry |= InstancePtr->GenFifoBus;
1242 GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX |
1243 XQSPIPSU_GENFIFO_STRIPE | XQSPIPSU_GENFIFO_POLL);
1244 GenFifoEntry |= XQSPIPSU_GENFIFO_CS_HOLD;
1246 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1247 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1250 /*****************************************************************************/
1253 * Read the specified number of bytes from RX FIFO
1255 * @param InstancePtr is a pointer to the XQspiPsu instance.
1256 * @param Msg is a pointer to the structure containing transfer data.
1257 * @param Size is the number of bytes to be read.
1263 ******************************************************************************/
1264 static inline void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,
1265 XQspiPsu_Msg *Msg, s32 Size)
1270 Xil_AssertVoid(InstancePtr != NULL);
1271 Xil_AssertVoid(Msg != NULL);
1273 while ((InstancePtr->RxBytes != 0) && (Count < Size)) {
1274 Data = XQspiPsu_ReadReg(InstancePtr->
1275 Config.BaseAddress, XQSPIPSU_RXD_OFFSET);
1276 if (InstancePtr->RxBytes >= 4) {
1277 (void)memcpy(Msg->RxBfrPtr, &Data, 4);
1278 InstancePtr->RxBytes -= 4;
1282 /* Read unaligned bytes (< 4 bytes) */
1283 (void)memcpy(Msg->RxBfrPtr, &Data, InstancePtr->RxBytes);
1284 Msg->RxBfrPtr += InstancePtr->RxBytes;
1285 Count += InstancePtr->RxBytes;
1286 InstancePtr->RxBytes = 0;