]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/qspipsu_v1_7/src/xqspipsu.c
60eee53ea4a6735bf43a614b749c23617eda6d07
[freertos] / FreeRTOS / Demo / CORTEX_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / qspipsu_v1_7 / src / xqspipsu.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2014 Xilinx, Inc.  All rights reserved.
4 *
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:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
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.
18 *
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
25 * SOFTWARE.
26 *
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.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xqspipsu.c
36 * @addtogroup qspipsu_v1_7
37 * @{
38 *
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.
41 *
42 * <pre>
43 * MODIFICATION HISTORY:
44 *
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.
55 * 1.1   sk  04/12/16 Added debug message prints.
56 * 1.2   nsk 07/01/16 Changed XQspiPsu_Select to support GQSPI and LQSPI
57 *                    selection.
58 *       rk  07/15/16 Added support for TapDelays at different frequencies.
59 *       nsk 08/05/16 Added example support PollData and PollTimeout
60 * 1.3   nsk 09/16/16 Update PollData and PollTimeout support for dual
61 *                    parallel configurations, modified XQspiPsu_PollData()
62 *                    and XQspiPsu_Create_PollConfigData()
63 * 1,5   nsk 08/14/17 Added CCI support
64 * 1.7   tjs     01/16/18 Removed the check for DMA MSB to be written. (CR#992560)
65 * 1.7   tjs 01/17/18 Added a support to toggle WP pin of the flash.
66 * 1.7   tjs     03/14/18 Added support in EL1 NS mode (CR#974882)
67 *
68 * </pre>
69 *
70 ******************************************************************************/
71
72 /***************************** Include Files *********************************/
73
74 #include "xqspipsu.h"
75
76 /************************** Constant Definitions *****************************/
77
78 /**************************** Type Definitions *******************************/
79
80 /***************** Macros (Inline Functions) Definitions *********************/
81
82 /************************** Function Prototypes ******************************/
83 static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
84                         u32 ByteCount);
85 static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode);
86 static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
87                         u32 *GenFifoEntry);
88 static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
89                         XQspiPsu_Msg *Msg, s32 Size);
90 static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
91                         XQspiPsu_Msg *Msg);
92 static inline void XQspiPsu_GenFifoEntryCSAssert(XQspiPsu *InstancePtr);
93 static inline void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr,
94                         XQspiPsu_Msg *Msg, s32 Index);
95 static inline void XQspiPsu_GenFifoEntryCSDeAssert(XQspiPsu *InstancePtr);
96 static inline void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,
97                         XQspiPsu_Msg *Msg, s32 Size);
98 static inline void XQspiPsu_PollData(XQspiPsu *QspiPsuPtr,
99                 XQspiPsu_Msg *FlashMsg);
100 static inline u32 XQspiPsu_Create_PollConfigData(XQspiPsu *QspiPsuPtr,
101                 XQspiPsu_Msg *FlashMsg);
102
103 /************************** Variable Definitions *****************************/
104
105 /*****************************************************************************/
106 /**
107 *
108 * Initializes a specific XQspiPsu instance such that the driver is ready to use.
109 *
110 *
111 * @param        InstancePtr is a pointer to the XQspiPsu instance.
112 * @param        ConfigPtr is a reference to a structure containing information
113 *               about a specific QSPIPSU device. This function initializes an
114 *               InstancePtr object for a specific device specified by the
115 *               contents of Config.
116 * @param        EffectiveAddr is the device base address in the virtual memory
117 *               address space. The caller is responsible for keeping the address
118 *               mapping from EffectiveAddr to the device physical base address
119 *               unchanged once this function is invoked. Unexpected errors may
120 *               occur if the address mapping changes after this function is
121 *               called. If address translation is not used, use
122 *               ConfigPtr->Config.BaseAddress for this device.
123 *
124 * @return
125 *               - XST_SUCCESS if successful.
126 *               - XST_DEVICE_IS_STARTED if the device is already started.
127 *               It must be stopped to re-initialize.
128 *
129 * @note         None.
130 *
131 ******************************************************************************/
132 s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr, XQspiPsu_Config *ConfigPtr,
133                                 u32 EffectiveAddr)
134 {
135         Xil_AssertNonvoid(InstancePtr != NULL);
136         Xil_AssertNonvoid(ConfigPtr != NULL);
137         s32 Status;
138
139         /*
140          * If the device is busy, disallow the initialize and return a status
141          * indicating it is already started. This allows the user to stop the
142          * device and re-initialize, but prevents a user from inadvertently
143          * initializing. This assumes the busy flag is cleared at startup.
144          */
145         if (InstancePtr->IsBusy == TRUE) {
146                 Status = (s32)XST_DEVICE_IS_STARTED;
147         } else {
148
149                 /* Set some default values. */
150                 InstancePtr->IsBusy = FALSE;
151
152                 InstancePtr->Config.BaseAddress = EffectiveAddr + XQSPIPSU_OFFSET;
153                 InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode;
154                 InstancePtr->StatusHandler = StubStatusHandler;
155                 InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
156                 InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
157                 InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
158                 /* Other instance variable initializations */
159                 InstancePtr->SendBufferPtr = NULL;
160                 InstancePtr->RecvBufferPtr = NULL;
161                 InstancePtr->GenFifoBufferPtr = NULL;
162                 InstancePtr->TxBytes = 0;
163                 InstancePtr->RxBytes = 0;
164                 InstancePtr->GenFifoEntries = 0;
165                 InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
166                 InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
167                 InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
168                 InstancePtr->IsUnaligned = 0;
169                 InstancePtr->IsManualstart = TRUE;
170
171                 /* Select QSPIPSU */
172                 XQspiPsu_Select(InstancePtr, XQSPIPSU_SEL_GQSPI_MASK);
173
174                 /*
175                  * Reset the QSPIPSU device to get it into its initial state. It is
176                  * expected that device configuration will take place after this
177                  * initialization is done, but before the device is started.
178                  */
179                 XQspiPsu_Reset(InstancePtr);
180
181                 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
182
183                 Status = XST_SUCCESS;
184         }
185
186         return Status;
187 }
188
189 /*****************************************************************************/
190 /**
191 *
192 * Resets the QSPIPSU device. Reset must only be called after the driver has
193 * been initialized. Any data transfer that is in progress is aborted.
194 *
195 * The upper layer software is responsible for re-configuring (if necessary)
196 * and restarting the QSPIPSU device after the reset.
197 *
198 * @param        InstancePtr is a pointer to the XQspiPsu instance.
199 *
200 * @return       None.
201 *
202 * @note         None.
203 *
204 ******************************************************************************/
205 void XQspiPsu_Reset(XQspiPsu *InstancePtr)
206 {
207         u32 ConfigReg;
208
209         Xil_AssertVoid(InstancePtr != NULL);
210
211         /* Abort any transfer that is in progress */
212         XQspiPsu_Abort(InstancePtr);
213
214         /* Default value to config register */
215         ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
216                         XQSPIPSU_CFG_OFFSET);
217
218         /* DMA mode */
219         ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
220         ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
221         /* Manual start */
222         ConfigReg |= XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK;
223         /* Little endain by default */
224         ConfigReg &= ~XQSPIPSU_CFG_ENDIAN_MASK;
225         /* Disable poll timeout */
226         ConfigReg &= ~XQSPIPSU_CFG_EN_POLL_TO_MASK;
227         /* Set hold bit */
228         ConfigReg |= XQSPIPSU_CFG_WP_HOLD_MASK;
229         /* Clear prescalar by default */
230         ConfigReg &= (u32)(~XQSPIPSU_CFG_BAUD_RATE_DIV_MASK);
231         /* CPOL CPHA 00 */
232         ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_PHA_MASK);
233         ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_POL_MASK);
234
235         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
236                 XQSPIPSU_CFG_OFFSET, ConfigReg);
237
238         /* Set by default to allow for high frequencies */
239         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
240                 XQSPIPSU_LPBK_DLY_ADJ_OFFSET,
241                 XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
242                         XQSPIPSU_LPBK_DLY_ADJ_OFFSET) |
243                         XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK);
244
245         /* Reset thresholds */
246         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
247                 XQSPIPSU_TX_THRESHOLD_OFFSET,
248                 XQSPIPSU_TX_FIFO_THRESHOLD_RESET_VAL);
249         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
250                 XQSPIPSU_RX_THRESHOLD_OFFSET,
251                 XQSPIPSU_RX_FIFO_THRESHOLD_RESET_VAL);
252         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
253                 XQSPIPSU_GF_THRESHOLD_OFFSET,
254                 XQSPIPSU_GEN_FIFO_THRESHOLD_RESET_VAL);
255
256         /* DMA init */
257         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
258                         XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET,
259                         XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL);
260
261 }
262
263 /*****************************************************************************/
264 /**
265 *
266 * Aborts a transfer in progress by
267 *
268 * @param        InstancePtr is a pointer to the XQspiPsu instance.
269 *
270 * @return       None.
271 *
272 * @note
273 *
274 ******************************************************************************/
275 void XQspiPsu_Abort(XQspiPsu *InstancePtr)
276 {
277
278         u32 IntrStatus, ConfigReg;
279
280         IntrStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
281                                         XQSPIPSU_ISR_OFFSET);
282
283         /* Clear and disable interrupts */
284         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
285                 XQSPIPSU_ISR_OFFSET, IntrStatus | XQSPIPSU_ISR_WR_TO_CLR_MASK);
286         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
287                         XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
288                 XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
289                                 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET));
290         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
291                         XQSPIPSU_QSPIDMA_DST_STS_OFFSET,
292                         XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
293                                 XQSPIPSU_QSPIDMA_DST_STS_OFFSET) |
294                                 XQSPIPSU_QSPIDMA_DST_STS_WTC);
295         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
296                 XQSPIPSU_IDR_OFFSET, XQSPIPSU_IDR_ALL_MASK);
297         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
298                         XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
299                         XQSPIPSU_QSPIDMA_DST_INTR_ALL_MASK);
300
301         /* Clear FIFO */
302         if((XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
303                         XQSPIPSU_ISR_OFFSET) & XQSPIPSU_ISR_RXEMPTY_MASK) != FALSE) {
304                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
305                         XQSPIPSU_FIFO_CTRL_OFFSET,
306                         XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_MASK |
307                         XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_MASK);
308         }
309
310         /*
311          * Switch to IO mode to Clear RX FIFO. This is becuase of DMA behaviour
312          * where it waits on RX empty and goes busy assuming there is data
313          * to be transfered even if there is no request.
314          */
315         if ((IntrStatus & XQSPIPSU_ISR_RXEMPTY_MASK) != 0U) {
316                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
317                                         XQSPIPSU_CFG_OFFSET);
318                 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
319                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
320                                 XQSPIPSU_CFG_OFFSET, ConfigReg);
321
322                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
323                                 XQSPIPSU_FIFO_CTRL_OFFSET,
324                                 XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK);
325
326                 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
327                         ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
328                         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
329                                         XQSPIPSU_CFG_OFFSET, ConfigReg);
330                 }
331         }
332
333         /* Disable QSPIPSU */
334         XQspiPsu_Disable(InstancePtr);
335
336         InstancePtr->TxBytes = 0;
337         InstancePtr->RxBytes = 0;
338         InstancePtr->GenFifoEntries = 0;
339         InstancePtr->IsBusy = FALSE;
340 }
341
342 /*****************************************************************************/
343 /**
344 *
345 * This function performs a transfer on the bus in polled mode. The messages
346 * passed are all transferred on the bus between one CS assert and de-assert.
347 *
348 * @param        InstancePtr is a pointer to the XQspiPsu instance.
349 * @param        Msg is a pointer to the structure containing transfer data.
350 * @param        NumMsg is the number of messages to be transferred.
351 *
352 * @return
353 *               - XST_SUCCESS if successful.
354 *               - XST_FAILURE if transfer fails.
355 *               - XST_DEVICE_BUSY if a transfer is already in progress.
356 *
357 * @note         None.
358 *
359 ******************************************************************************/
360 s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
361                                 u32 NumMsg)
362 {
363
364         s32 Index;
365         u32 QspiPsuStatusReg;
366         u32 BaseAddress;
367         s32 RxThr;
368         u32 IOPending = (u32)FALSE;
369
370         Xil_AssertNonvoid(InstancePtr != NULL);
371         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
372         for (Index = 0; Index < (s32)NumMsg; Index++) {
373                 Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
374         }
375
376         /* Check whether there is another transfer in progress. Not thread-safe */
377         if (InstancePtr->IsBusy == TRUE) {
378                 return (s32)XST_DEVICE_BUSY;
379         }
380
381         /* Check for ByteCount upper limit - 2^28 for DMA */
382         for (Index = 0; Index < (s32)NumMsg; Index++) {
383                 if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
384                                 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
385                         return (s32)XST_FAILURE;
386                 }
387         }
388
389         /*
390          * Set the busy flag, which will be cleared when the transfer is
391          * entirely done.
392          */
393         InstancePtr->IsBusy = TRUE;
394
395         BaseAddress = InstancePtr->Config.BaseAddress;
396
397         /* Enable */
398         XQspiPsu_Enable(InstancePtr);
399
400         /* Select slave */
401         XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
402
403         /* list */
404         Index = 0;
405         while (Index < (s32)NumMsg) {
406                 XQspiPsu_GenFifoEntryData(InstancePtr, Msg, Index);
407
408                 if (InstancePtr->IsManualstart == TRUE) {
409 #ifdef DEBUG
410         xil_printf("\nManual Start\r\n");
411 #endif
412                         XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
413                                 XQspiPsu_ReadReg(BaseAddress,
414                                         XQSPIPSU_CFG_OFFSET) |
415                                         XQSPIPSU_CFG_START_GEN_FIFO_MASK);
416                 }
417
418                 /* Use thresholds here */
419                 /* If there is more data to be transmitted */
420                 do {
421                         QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
422                                                 XQSPIPSU_ISR_OFFSET);
423
424                         /* Transmit more data if left */
425                         if (((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
426                                 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
427                                 (InstancePtr->TxBytes > 0)) {
428                                 XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
429                                                 XQSPIPSU_TXD_DEPTH);
430                         }
431
432                         /* Check if DMA RX is complete and update RxBytes */
433                         if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
434                                 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
435                                 u32 DmaIntrSts;
436                                 DmaIntrSts = XQspiPsu_ReadReg(BaseAddress,
437                                                                 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
438                                 if ((DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
439                                         XQspiPsu_WriteReg(BaseAddress,
440                                                 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
441                                                 DmaIntrSts);
442                                         /* Read remaining bytes using IO mode */
443                                         if((InstancePtr->RxBytes % 4) != 0 ) {
444                                                 XQspiPsu_WriteReg(BaseAddress,
445                                                         XQSPIPSU_CFG_OFFSET,
446                                                         (XQspiPsu_ReadReg(BaseAddress,
447                                                         XQSPIPSU_CFG_OFFSET) &
448                                                         ~XQSPIPSU_CFG_MODE_EN_MASK));
449                                                 InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
450                                                 Msg[Index].ByteCount =
451                                                         (InstancePtr->RxBytes % 4);
452                                                 Msg[Index].RxBfrPtr += (InstancePtr->RxBytes -
453                                                                 (InstancePtr->RxBytes % 4));
454                                                 InstancePtr->IsUnaligned = 1;
455                                                 IOPending = (u32)TRUE;
456                                                 break;
457                                         }
458                                         InstancePtr->RxBytes = 0;
459                                 }
460                         } else {
461                                 if ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) {
462                                         /* Check if PIO RX is complete and update RxBytes */
463                                         RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
464                                                         XQSPIPSU_RX_THRESHOLD_OFFSET);
465                                         if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
466                                                                         != 0U) {
467                                                 XQspiPsu_ReadRxFifo(InstancePtr,
468                                                                 &Msg[Index], RxThr*4);
469
470                                         } else {
471                                                 if ((QspiPsuStatusReg &
472                                                         XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
473                                                                 XQspiPsu_ReadRxFifo(InstancePtr,
474                                                                         &Msg[Index], InstancePtr->RxBytes);
475                                                 }
476                                         }
477                                 }
478                         }
479                 } while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) ||
480                         (InstancePtr->TxBytes != 0) ||
481                         ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == FALSE) ||
482                         (InstancePtr->RxBytes != 0));
483
484                 if((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
485                         InstancePtr->IsUnaligned = 0;
486                         XQspiPsu_WriteReg(BaseAddress,
487                                 XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
488                                 BaseAddress,
489                                 XQSPIPSU_CFG_OFFSET) |
490                                 XQSPIPSU_CFG_MODE_EN_DMA_MASK));
491                         InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
492                 }
493
494                 if (IOPending == (u32)TRUE) {
495                         IOPending = (u32)FALSE;
496                 } else {
497                         Index++;
498                 }
499         }
500
501         /* De-select slave */
502         XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
503
504         if (InstancePtr->IsManualstart == TRUE) {
505 #ifdef DEBUG
506         xil_printf("\nManual Start\r\n");
507 #endif
508                 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
509                         XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
510                                 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
511         }
512
513         QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
514         while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) {
515                 QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
516                                                 XQSPIPSU_ISR_OFFSET);
517         }
518
519         /* Clear the busy flag. */
520         InstancePtr->IsBusy = FALSE;
521
522         /* Disable the device. */
523         XQspiPsu_Disable(InstancePtr);
524
525         return XST_SUCCESS;
526 }
527
528 /*****************************************************************************/
529 /**
530 *
531 * This function initiates a transfer on the bus and enables interrupts.
532 * The transfer is completed by the interrupt handler. The messages passed are
533 * all transferred on the bus between one CS assert and de-assert.
534 *
535 * @param        InstancePtr is a pointer to the XQspiPsu instance.
536 * @param        Msg is a pointer to the structure containing transfer data.
537 * @param        NumMsg is the number of messages to be transferred.
538 *
539 * @return
540 *               - XST_SUCCESS if successful.
541 *               - XST_FAILURE if transfer fails.
542 *               - XST_DEVICE_BUSY if a transfer is already in progress.
543 *
544 * @note         None.
545 *
546 ******************************************************************************/
547 s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
548                                 u32 NumMsg)
549 {
550
551         s32 Index;
552         u32 BaseAddress;
553
554         Xil_AssertNonvoid(InstancePtr != NULL);
555         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
556         for (Index = 0; Index < (s32)NumMsg; Index++) {
557                 Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
558         }
559
560         /* Check whether there is another transfer in progress. Not thread-safe */
561         if (InstancePtr->IsBusy == TRUE) {
562                 return (s32)XST_DEVICE_BUSY;
563         }
564
565         if (Msg[0].Flags & XQSPIPSU_MSG_FLAG_POLL) {
566                 InstancePtr->IsBusy = TRUE;
567                 XQspiPsu_PollData(InstancePtr, Msg);
568         } else {
569                 /* Check for ByteCount upper limit - 2^28 for DMA */
570                 for (Index = 0; Index < (s32)NumMsg; Index++) {
571                         if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
572                                         ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
573                         return (s32)XST_FAILURE;
574                 }
575         }
576
577         /*
578          * Set the busy flag, which will be cleared when the transfer is
579          * entirely done.
580          */
581         InstancePtr->IsBusy = TRUE;
582
583         BaseAddress = InstancePtr->Config.BaseAddress;
584
585         InstancePtr->Msg = Msg;
586         InstancePtr->NumMsg = (s32)NumMsg;
587         InstancePtr->MsgCnt = 0;
588
589         /* Enable */
590         XQspiPsu_Enable(InstancePtr);
591
592         /* Select slave */
593         XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
594
595         /* This might not work if not manual start */
596         /* Put first message in FIFO along with the above slave select */
597         XQspiPsu_GenFifoEntryData(InstancePtr, Msg, 0);
598
599         if (InstancePtr->IsManualstart == TRUE) {
600 #ifdef DEBUG
601         xil_printf("\nManual Start\r\n");
602 #endif
603                 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
604                         XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
605                                 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
606         }
607
608         /* Enable interrupts */
609         XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IER_OFFSET,
610                 (u32)XQSPIPSU_IER_TXNOT_FULL_MASK | (u32)XQSPIPSU_IER_TXEMPTY_MASK |
611                 (u32)XQSPIPSU_IER_RXNEMPTY_MASK | (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
612                 (u32)XQSPIPSU_IER_RXEMPTY_MASK);
613
614         if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
615                 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
616                                 XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
617         }
618         }
619         return XST_SUCCESS;
620 }
621
622 /*****************************************************************************/
623 /**
624 *
625 * Handles interrupt based transfers by acting on GENFIFO and DMA interurpts.
626 *
627 * @param        InstancePtr is a pointer to the XQspiPsu instance.
628 *
629 * @return
630 *               - XST_SUCCESS if successful.
631 *               - XST_FAILURE if transfer fails.
632 *
633 * @note         None.
634 *
635 ******************************************************************************/
636 s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr)
637 {
638         u32 QspiPsuStatusReg, DmaIntrStatusReg = 0;
639         u32 BaseAddress;
640         XQspiPsu_Msg *Msg;
641         s32 NumMsg;
642         s32 MsgCnt;
643         u8 DeltaMsgCnt = 0;
644         s32 RxThr;
645         u32 TxRxFlag;
646
647         Xil_AssertNonvoid(InstancePtr != NULL);
648
649         BaseAddress = InstancePtr->Config.BaseAddress;
650         Msg = InstancePtr->Msg;
651         NumMsg = InstancePtr->NumMsg;
652         MsgCnt = InstancePtr->MsgCnt;
653         TxRxFlag = Msg[MsgCnt].Flags;
654
655         /* QSPIPSU Intr cleared on read */
656         QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
657         if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
658                 /* DMA Intr write to clear */
659                 DmaIntrStatusReg = XQspiPsu_ReadReg(BaseAddress,
660                                         XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
661
662                 XQspiPsu_WriteReg(BaseAddress,
663                         XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrStatusReg);
664         }
665         if (((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK) != FALSE)) {
666                 /* Call status handler to indicate error */
667                 InstancePtr->StatusHandler(InstancePtr->StatusRef,
668                                         XST_SPI_COMMAND_ERROR, 0);
669         }
670
671         /* Fill more data to be txed if required */
672         if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
673                 ((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
674                 (InstancePtr->TxBytes > 0)) {
675                 XQspiPsu_FillTxFifo(InstancePtr, &Msg[MsgCnt],
676                                 XQSPIPSU_TXD_DEPTH);
677         }
678
679         /*
680          * Check if the entry is ONLY TX and increase MsgCnt.
681          * This is to allow TX and RX together in one entry - corner case.
682          */
683         if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
684                 ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) != FALSE) &&
685                 ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
686                 (InstancePtr->TxBytes == 0) &&
687                 ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE)) {
688                 MsgCnt += 1;
689                 DeltaMsgCnt = 1U;
690         }
691
692         if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
693                 (MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
694                 if ((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
695                                 /* Read remaining bytes using IO mode */
696                         if((InstancePtr->RxBytes % 4) != 0 ) {
697                                 XQspiPsu_WriteReg(BaseAddress,
698                                         XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
699                                         BaseAddress, XQSPIPSU_CFG_OFFSET) &
700                                         ~XQSPIPSU_CFG_MODE_EN_MASK));
701                                 InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
702                                 Msg[MsgCnt].ByteCount = (InstancePtr->RxBytes % 4);
703                                 Msg[MsgCnt].RxBfrPtr += (InstancePtr->RxBytes -
704                                                 (InstancePtr->RxBytes % 4));
705                                 InstancePtr->IsUnaligned = 1;
706                                 XQspiPsu_GenFifoEntryData(InstancePtr, Msg,
707                                                 MsgCnt);
708                                 if(InstancePtr->IsManualstart == TRUE) {
709 #ifdef DEBUG
710         xil_printf("\nManual Start\r\n");
711 #endif
712                                         XQspiPsu_WriteReg(BaseAddress,
713                                                 XQSPIPSU_CFG_OFFSET,
714                                                 XQspiPsu_ReadReg(BaseAddress,
715                                                 XQSPIPSU_CFG_OFFSET) |
716                                                 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
717                                 }
718                         }
719                         else {
720                                 InstancePtr->RxBytes = 0;
721                                 MsgCnt += 1;
722                                 DeltaMsgCnt = 1U;
723                         }
724                 }
725         } else {
726                 if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
727                         if (InstancePtr->RxBytes != 0) {
728                                 if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
729                                                                 != FALSE) {
730                                         RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
731                                                                 XQSPIPSU_RX_THRESHOLD_OFFSET);
732                                         XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
733                                                 RxThr*4);
734                                 } else {
735                                         if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
736                                                 ((QspiPsuStatusReg & XQSPIPSU_ISR_RXEMPTY_MASK) == FALSE)) {
737                                                 XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
738                                                         InstancePtr->RxBytes);
739                                         }
740                                 }
741                                 if (InstancePtr->RxBytes == 0) {
742                                         MsgCnt += 1;
743                                         DeltaMsgCnt = 1U;
744                                 }
745                         }
746                 }
747         }
748
749         /*
750          * Dummy byte transfer
751          * MsgCnt < NumMsg check is to ensure is it a valid dummy cycle message
752          * If one of the above conditions increased MsgCnt, then
753          * the new message is yet to be placed in the FIFO; hence !DeltaMsgCnt.
754          */
755         if ((MsgCnt < NumMsg) && (DeltaMsgCnt == FALSE) &&
756                 ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE) &&
757                 ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) == FALSE) &&
758                 ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) == FALSE) &&
759                 ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE)) {
760                 MsgCnt += 1;
761                 DeltaMsgCnt = 1U;
762         }
763         InstancePtr->MsgCnt = MsgCnt;
764
765         /*
766          * DeltaMsgCnt is to handle conditions where genfifo empty can be set
767          * while tx is still not empty or rx dma is not yet done.
768          * MsgCnt > NumMsg indicates CS de-assert entry was also executed.
769          */
770         if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
771                 ((DeltaMsgCnt != FALSE) || (MsgCnt > NumMsg))) {
772                 if (MsgCnt < NumMsg) {
773                         if(InstancePtr->IsUnaligned != 0) {
774                                 InstancePtr->IsUnaligned = 0;
775                                 XQspiPsu_WriteReg(InstancePtr->Config.
776                                         BaseAddress, XQSPIPSU_CFG_OFFSET,
777                                         (XQspiPsu_ReadReg(InstancePtr->Config.
778                                         BaseAddress, XQSPIPSU_CFG_OFFSET) |
779                                         XQSPIPSU_CFG_MODE_EN_DMA_MASK));
780                                 InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
781                         }
782                         /* This might not work if not manual start */
783                         XQspiPsu_GenFifoEntryData(InstancePtr, Msg, MsgCnt);
784
785                         if (InstancePtr->IsManualstart == TRUE) {
786 #ifdef DEBUG
787         xil_printf("\nManual Start\r\n");
788 #endif
789                                 XQspiPsu_WriteReg(BaseAddress,
790                                         XQSPIPSU_CFG_OFFSET,
791                                         XQspiPsu_ReadReg(BaseAddress,
792                                                 XQSPIPSU_CFG_OFFSET) |
793                                                 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
794                         }
795                 } else if (MsgCnt == NumMsg) {
796                         /* This is just to keep track of the de-assert entry */
797                         MsgCnt += 1;
798                         InstancePtr->MsgCnt = MsgCnt;
799
800                         /* De-select slave */
801                         XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
802
803                         if (InstancePtr->IsManualstart == TRUE) {
804 #ifdef DEBUG
805         xil_printf("\nManual Start\r\n");
806 #endif
807                                 XQspiPsu_WriteReg(BaseAddress,
808                                         XQSPIPSU_CFG_OFFSET,
809                                         XQspiPsu_ReadReg(BaseAddress,
810                                                 XQSPIPSU_CFG_OFFSET) |
811                                                 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
812                         }
813                 } else {
814                         /* Disable interrupts */
815                         XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IDR_OFFSET,
816                                         (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
817                                         (u32)XQSPIPSU_IER_TXEMPTY_MASK |
818                                         (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
819                                         (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
820                                         (u32)XQSPIPSU_IER_RXEMPTY_MASK);
821                         if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
822                                 XQspiPsu_WriteReg(BaseAddress,
823                                         XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
824                                         XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
825                         }
826
827                         /* Clear the busy flag. */
828                         InstancePtr->IsBusy = FALSE;
829
830                         /* Disable the device. */
831                         XQspiPsu_Disable(InstancePtr);
832
833                         /* Call status handler to indicate completion */
834                         InstancePtr->StatusHandler(InstancePtr->StatusRef,
835                                                 XST_SPI_TRANSFER_DONE, 0);
836                 }
837         }
838         if ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) != FALSE){
839                  if (QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK){
840                          /*
841                           * Read data from RXFIFO, since when data from the flash device
842                           * (status data) matched with configured value in poll_cfg, then
843                           * controller writes the matched data into RXFIFO.
844                           */
845                         XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_RXD_OFFSET);
846
847                         XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IDR_OFFSET,
848                                         (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
849                                         (u32)XQSPIPSU_IER_TXEMPTY_MASK |
850                                         (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
851                                         (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
852                                         (u32)XQSPIPSU_IER_RXEMPTY_MASK |
853                                         (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
854                         InstancePtr->StatusHandler(InstancePtr->StatusRef, XST_SPI_POLL_DONE, 0);
855
856                         InstancePtr->IsBusy = FALSE;
857                         /* Disable the device. */
858                         XQspiPsu_Disable(InstancePtr);
859
860                  }
861                  if (QspiPsuStatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK){
862                         InstancePtr->StatusHandler(InstancePtr->StatusRef,
863                                         XST_FLASH_TIMEOUT_ERROR, 0);
864                  }
865         }
866         return XST_SUCCESS;
867 }
868
869 /*****************************************************************************/
870 /**
871 *
872 * Sets the status callback function, the status handler, which the driver
873 * calls when it encounters conditions that should be reported to upper
874 * layer software. The handler executes in an interrupt context, so it must
875 * minimize the amount of processing performed. One of the following status
876 * events is passed to the status handler.
877 *
878 * <pre>
879 *
880 * XST_SPI_TRANSFER_DONE         The requested data transfer is done
881 *
882 * XST_SPI_TRANSMIT_UNDERRUN     As a slave device, the master clocked data
883 *                               but there were none available in the transmit
884 *                               register/FIFO. This typically means the slave
885 *                               application did not issue a transfer request
886 *                               fast enough, or the processor/driver could not
887 *                               fill the transmit register/FIFO fast enough.
888 *
889 * XST_SPI_RECEIVE_OVERRUN       The QSPIPSU device lost data. Data was received
890 *                               but the receive data register/FIFO was full.
891 *
892 * </pre>
893 * @param        InstancePtr is a pointer to the XQspiPsu instance.
894 * @param        CallBackRef is the upper layer callback reference passed back
895 *               when the callback function is invoked.
896 * @param        FuncPointer is the pointer to the callback function.
897 *
898 * @return       None.
899 *
900 * @note
901 *
902 * The handler is called within interrupt context, so it should do its work
903 * quickly and queue potentially time-consuming work to a task-level thread.
904 *
905 ******************************************************************************/
906 void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
907                                 XQspiPsu_StatusHandler FuncPointer)
908 {
909         Xil_AssertVoid(InstancePtr != NULL);
910         Xil_AssertVoid(FuncPointer != NULL);
911         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
912
913         InstancePtr->StatusHandler = FuncPointer;
914         InstancePtr->StatusRef = CallBackRef;
915 }
916
917 /*****************************************************************************/
918 /**
919 *
920 * This is a stub for the status callback. The stub is here in case the upper
921 * layers forget to set the handler.
922 *
923 * @param        CallBackRef is a pointer to the upper layer callback reference
924 * @param        StatusEvent is the event that just occurred.
925 * @param        ByteCount is the number of bytes transferred up until the event
926 *               occurred.
927 *
928 * @return       None.
929 *
930 * @note         None.
931 *
932 ******************************************************************************/
933 static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
934                                 u32 ByteCount)
935 {
936         (void) CallBackRef;
937         (void) StatusEvent;
938         (void) ByteCount;
939
940         Xil_AssertVoidAlways();
941 }
942
943 /*****************************************************************************/
944 /**
945 *
946 * Selects SPI mode - x1 or x2 or x4.
947 *
948 * @param        SpiMode - spi or dual or quad.
949 * @return       Mask to set desired SPI mode in GENFIFO entry.
950 *
951 * @note         None.
952 *
953 ******************************************************************************/
954 static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode)
955 {
956         u32 Mask;
957
958 #ifdef DEBUG
959         xil_printf("\nXQspiPsu_SelectSpiMode\r\n");
960 #endif
961
962         switch (SpiMode) {
963                 case XQSPIPSU_SELECT_MODE_DUALSPI:
964                         Mask = XQSPIPSU_GENFIFO_MODE_DUALSPI;
965                         break;
966                 case XQSPIPSU_SELECT_MODE_QUADSPI:
967                         Mask = XQSPIPSU_GENFIFO_MODE_QUADSPI;
968                         break;
969                 case XQSPIPSU_SELECT_MODE_SPI:
970                         Mask = XQSPIPSU_GENFIFO_MODE_SPI;
971                         break;
972                 default:
973                         Mask = XQSPIPSU_GENFIFO_MODE_SPI;
974                         break;
975         }
976 #ifdef DEBUG
977         xil_printf("\nSPIMode is %08x\r\n", SpiMode);
978 #endif
979
980         return Mask;
981 }
982
983 /*****************************************************************************/
984 /**
985 *
986 * This function checks the TX/RX buffers in the message and setups up the
987 * GENFIFO entries, TX FIFO or RX DMA as required.
988 *
989 * @param        InstancePtr is a pointer to the XQspiPsu instance.
990 * @param        Msg is a pointer to the structure containing transfer data.
991 * @param        GenFifoEntry is pointer to the variable in which GENFIFO mask
992 *               is returned to calling function
993 *
994 * @return       None
995 *
996 * @note         None.
997 *
998 ******************************************************************************/
999 static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
1000                                         u32 *GenFifoEntry)
1001 {
1002         Xil_AssertVoid(InstancePtr != NULL);
1003
1004         /* Transmit */
1005         if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
1006                         ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == FALSE)) {
1007                 /* Setup data to be TXed */
1008                 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
1009                 *GenFifoEntry |= XQSPIPSU_GENFIFO_TX;
1010                 InstancePtr->TxBytes = (s32)Msg->ByteCount;
1011                 InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
1012                 InstancePtr->RecvBufferPtr = NULL;
1013                 XQspiPsu_FillTxFifo(InstancePtr, Msg, XQSPIPSU_TXD_DEPTH);
1014                 /* Discard RX data */
1015                 *GenFifoEntry &= ~XQSPIPSU_GENFIFO_RX;
1016                 InstancePtr->RxBytes = 0;
1017         }
1018
1019         /* Receive */
1020         if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) &&
1021                         ((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == FALSE)) {
1022                 /* TX auto fill */
1023                 *GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX;
1024                 InstancePtr->TxBytes = 0;
1025                 /* Setup RX */
1026                 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
1027                 *GenFifoEntry |= XQSPIPSU_GENFIFO_RX;
1028                 InstancePtr->RxBytes = (s32)Msg->ByteCount;
1029                 InstancePtr->SendBufferPtr = NULL;
1030                 InstancePtr->RecvBufferPtr = Msg->RxBfrPtr;
1031                 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
1032                         XQspiPsu_SetupRxDma(InstancePtr, Msg);
1033                 }
1034         }
1035
1036         /* If only dummy is requested as a separate entry */
1037         if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == FALSE) &&
1038                         (Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == FALSE) {
1039                 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
1040                 *GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
1041                 InstancePtr->TxBytes = 0;
1042                 InstancePtr->RxBytes = 0;
1043                 InstancePtr->SendBufferPtr = NULL;
1044                 InstancePtr->RecvBufferPtr = NULL;
1045         }
1046
1047         /* Dummy and cmd sent by upper layer to received data */
1048         if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
1049                         ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
1050                 *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
1051                 *GenFifoEntry |= (XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
1052                 InstancePtr->TxBytes = (s32)Msg->ByteCount;
1053                 InstancePtr->RxBytes = (s32)Msg->ByteCount;
1054                 InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
1055                 InstancePtr->RecvBufferPtr = Msg->RxBfrPtr;
1056                 XQspiPsu_FillTxFifo(InstancePtr, Msg, XQSPIPSU_TXD_DEPTH);
1057                 /* Add check for DMA or PIO here */
1058                 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
1059                         XQspiPsu_SetupRxDma(InstancePtr, Msg);
1060                 }
1061         }
1062 }
1063
1064 /*****************************************************************************/
1065 /**
1066 *
1067 * Fills the TX FIFO as long as there is room in the FIFO or the bytes required
1068 * to be transmitted.
1069 *
1070 * @param        InstancePtr is a pointer to the XQspiPsu instance.
1071 * @param        Msg is a pointer to the structure containing transfer data.
1072 * @param        Size is the number of bytes to be transmitted.
1073 *
1074 * @return       None
1075 *
1076 * @note         None.
1077 *
1078 ******************************************************************************/
1079 static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
1080                                         XQspiPsu_Msg *Msg, s32 Size)
1081 {
1082         s32 Count = 0;
1083         u32 Data;
1084
1085         Xil_AssertVoid(InstancePtr != NULL);
1086
1087 #ifdef DEBUG
1088         xil_printf("\nXQspiPsu_FillTxFifo\r\n");
1089 #endif
1090
1091         while ((InstancePtr->TxBytes > 0) && (Count < Size)) {
1092                 if (InstancePtr->TxBytes >= 4) {
1093                         (void)memcpy(&Data, Msg->TxBfrPtr, 4);
1094                         Msg->TxBfrPtr += 4;
1095                         InstancePtr->TxBytes -= 4;
1096                         Count += 4;
1097                 } else {
1098                         (void)memcpy(&Data, Msg->TxBfrPtr, InstancePtr->TxBytes);
1099                         Msg->TxBfrPtr += InstancePtr->TxBytes;
1100                         Count += InstancePtr->TxBytes;
1101                         InstancePtr->TxBytes = 0;
1102                 }
1103                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1104                                 XQSPIPSU_TXD_OFFSET, Data);
1105 #ifdef DEBUG
1106         xil_printf("\nData is %08x\r\n", Data);
1107 #endif
1108
1109         }
1110         if (InstancePtr->TxBytes < 0) {
1111                 InstancePtr->TxBytes = 0;
1112         }
1113 }
1114
1115 /*****************************************************************************/
1116 /**
1117 *
1118 * This function sets up the RX DMA operation.
1119 *
1120 * @param        InstancePtr is a pointer to the XQspiPsu instance.
1121 * @param        Msg is a pointer to the structure containing transfer data.
1122 *
1123 * @return       None
1124 *
1125 * @note         None.
1126 *
1127 ******************************************************************************/
1128 static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
1129                                         XQspiPsu_Msg *Msg)
1130 {
1131         s32 Remainder;
1132         s32 DmaRxBytes;
1133         u64 AddrTemp;
1134
1135         Xil_AssertVoid(InstancePtr != NULL);
1136
1137         AddrTemp = (u64)((INTPTR)(Msg->RxBfrPtr) &
1138                                 XQSPIPSU_QSPIDMA_DST_ADDR_MASK);
1139         /* Check for RXBfrPtr to be word aligned */
1140         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1141                         XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET,
1142                         (u32)AddrTemp);
1143
1144 #ifdef __aarch64__
1145         AddrTemp = (u64)((INTPTR)(Msg->RxBfrPtr) >> 32);
1146         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1147                         XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET,
1148                         (u32)AddrTemp &
1149                         XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
1150 #endif
1151
1152         Remainder = InstancePtr->RxBytes % 4;
1153         DmaRxBytes = InstancePtr->RxBytes;
1154         if (Remainder != 0) {
1155                 /* This is done to make Dma bytes aligned */
1156                 DmaRxBytes = InstancePtr->RxBytes - Remainder;
1157                 Msg->ByteCount = (u32)DmaRxBytes;
1158         }
1159         if (InstancePtr->Config.IsCacheCoherent == 0) {
1160                 Xil_DCacheInvalidateRange((INTPTR)InstancePtr->RecvBufferPtr,
1161                         Msg->ByteCount);
1162         }
1163
1164         /* Write no. of words to DMA DST SIZE */
1165         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1166                         XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
1167
1168 }
1169
1170 /*****************************************************************************/
1171 /**
1172 *
1173 * This function writes the GENFIFO entry to assert CS.
1174 *
1175 * @param        InstancePtr is a pointer to the XQspiPsu instance.
1176 *
1177 * @return       None
1178 *
1179 * @note         None.
1180 *
1181 ******************************************************************************/
1182 static inline void XQspiPsu_GenFifoEntryCSAssert(XQspiPsu *InstancePtr)
1183 {
1184         u32 GenFifoEntry;
1185
1186 #ifdef DEBUG
1187         xil_printf("\nXQspiPsu_GenFifoEntryCSAssert\r\n");
1188 #endif
1189
1190         GenFifoEntry = 0x0U;
1191         GenFifoEntry &= ~((u32)XQSPIPSU_GENFIFO_DATA_XFER | (u32)XQSPIPSU_GENFIFO_EXP);
1192         GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
1193         GenFifoEntry |= XQSPIPSU_GENFIFO_MODE_SPI;
1194         GenFifoEntry |= InstancePtr->GenFifoCS;
1195         GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
1196         GenFifoEntry |= InstancePtr->GenFifoBus;
1197         GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX |
1198                         XQSPIPSU_GENFIFO_STRIPE | XQSPIPSU_GENFIFO_POLL);
1199         GenFifoEntry |= XQSPIPSU_GENFIFO_CS_SETUP;
1200 #ifdef DEBUG
1201         xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1202 #endif
1203         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1204                 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1205 }
1206
1207 /*****************************************************************************/
1208 /**
1209 *
1210 * This function writes the GENFIFO entries to transmit the messages requested.
1211 *
1212 * @param        InstancePtr is a pointer to the XQspiPsu instance.
1213 * @param        Msg is a pointer to the structure containing transfer data.
1214 * @param        Index of the current message to be handled.
1215 *
1216 * @return
1217 *               - XST_SUCCESS if successful.
1218 *               - XST_FAILURE if transfer fails.
1219 *               - XST_DEVICE_BUSY if a transfer is already in progress.
1220 *
1221 * @note         None.
1222 *
1223 ******************************************************************************/
1224 static inline void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr,
1225                                                 XQspiPsu_Msg *Msg, s32 Index)
1226 {
1227         u32 GenFifoEntry;
1228         u32 BaseAddress;
1229         u32 TempCount;
1230         u32 ImmData;
1231
1232 #ifdef DEBUG
1233         xil_printf("\nXQspiPsu_GenFifoEntryData\r\n");
1234 #endif
1235
1236         BaseAddress = InstancePtr->Config.BaseAddress;
1237
1238         GenFifoEntry = 0x0U;
1239         /* Bus width */
1240         GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
1241         GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg[Index].BusWidth);
1242
1243         GenFifoEntry |= InstancePtr->GenFifoCS;
1244         GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
1245         GenFifoEntry |= InstancePtr->GenFifoBus;
1246
1247         /* Data */
1248         if (((Msg[Index].Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != FALSE) {
1249                 GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
1250         } else {
1251                 GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
1252         }
1253
1254         /* If Byte Count is less than 8 bytes do the transfer in IO mode */
1255         if ((Msg[Index].ByteCount < 8U) &&
1256                 (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA)) {
1257                         InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
1258                         XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
1259                                 (XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) &
1260                                                 ~XQSPIPSU_CFG_MODE_EN_MASK));
1261                         InstancePtr->IsUnaligned = 1;
1262         }
1263
1264         XQspiPsu_TXRXSetup(InstancePtr, &Msg[Index], &GenFifoEntry);
1265
1266         if (Msg[Index].ByteCount < XQSPIPSU_GENFIFO_IMM_DATA_MASK) {
1267                 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
1268                 GenFifoEntry |= Msg[Index].ByteCount;
1269 #ifdef DEBUG
1270         xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1271 #endif
1272                 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
1273                                 GenFifoEntry);
1274         } else {
1275                 TempCount = Msg[Index].ByteCount;
1276                 u32 Exponent = 8;       /* 2^8 = 256 */
1277
1278                 ImmData = TempCount & 0xFFU;
1279                 /* Exponent entries */
1280                 GenFifoEntry |= XQSPIPSU_GENFIFO_EXP;
1281                 while (TempCount != 0U) {
1282                         if ((TempCount & XQSPIPSU_GENFIFO_EXP_START) != FALSE) {
1283                                 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
1284                                 GenFifoEntry |= Exponent;
1285 #ifdef DEBUG
1286         xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1287 #endif
1288                                 XQspiPsu_WriteReg(BaseAddress,
1289                                         XQSPIPSU_GEN_FIFO_OFFSET,
1290                                         GenFifoEntry);
1291                         }
1292                         TempCount = TempCount >> 1;
1293                         Exponent++;
1294                 }
1295
1296                 /* Immediate entry */
1297                 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_EXP);
1298                 if ((ImmData & 0xFFU) != FALSE) {
1299                         GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
1300                         GenFifoEntry |= ImmData & 0xFFU;
1301 #ifdef DEBUG
1302         xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1303 #endif
1304                         XQspiPsu_WriteReg(BaseAddress,
1305                                 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1306                 }
1307         }
1308
1309         /* One dummy GenFifo entry in case of IO mode */
1310         if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) &&
1311                         ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
1312                 GenFifoEntry = 0x0U;
1313 #ifdef DEBUG
1314         xil_printf("\nDummy FifoEntry=%08x\r\n",GenFifoEntry);
1315 #endif
1316                 XQspiPsu_WriteReg(BaseAddress,
1317                                 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1318         }
1319 }
1320
1321 /*****************************************************************************/
1322 /**
1323 *
1324 * This function writes the GENFIFO entry to de-assert CS.
1325 *
1326 * @param        InstancePtr is a pointer to the XQspiPsu instance.
1327 *
1328 * @return       None
1329 *
1330 * @note         None.
1331 *
1332 ******************************************************************************/
1333 static inline void XQspiPsu_GenFifoEntryCSDeAssert(XQspiPsu *InstancePtr)
1334 {
1335         u32 GenFifoEntry;
1336
1337 #ifdef DEBUG
1338         xil_printf("\nXQspiPsu_GenFifoEntryCSDeAssert\r\n");
1339 #endif
1340
1341         GenFifoEntry = 0x0U;
1342         GenFifoEntry &= ~((u32)XQSPIPSU_GENFIFO_DATA_XFER | (u32)XQSPIPSU_GENFIFO_EXP);
1343         GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
1344         GenFifoEntry |= XQSPIPSU_GENFIFO_MODE_SPI;
1345         GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
1346         GenFifoEntry |= InstancePtr->GenFifoBus;
1347         GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX |
1348                         XQSPIPSU_GENFIFO_STRIPE | XQSPIPSU_GENFIFO_POLL);
1349         GenFifoEntry |= XQSPIPSU_GENFIFO_CS_HOLD;
1350 #ifdef DEBUG
1351         xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1352 #endif
1353         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1354                 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1355 }
1356
1357 /*****************************************************************************/
1358 /**
1359 *
1360 * Read the specified number of bytes from RX FIFO
1361 *
1362 * @param        InstancePtr is a pointer to the XQspiPsu instance.
1363 * @param        Msg is a pointer to the structure containing transfer data.
1364 * @param        Size is the number of bytes to be read.
1365 *
1366 * @return       None
1367 *
1368 * @note         None.
1369 *
1370 ******************************************************************************/
1371 static inline void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,
1372                                         XQspiPsu_Msg *Msg, s32 Size)
1373 {
1374         s32 Count = 0;
1375         u32 Data;
1376
1377 #ifdef DEBUG
1378         xil_printf("\nXQspiPsu_ReadRxFifo\r\n");
1379 #endif
1380
1381         Xil_AssertVoid(InstancePtr != NULL);
1382         Xil_AssertVoid(Msg != NULL);
1383
1384         while ((InstancePtr->RxBytes != 0) && (Count < Size)) {
1385                 Data = XQspiPsu_ReadReg(InstancePtr->
1386                                 Config.BaseAddress, XQSPIPSU_RXD_OFFSET);
1387 #ifdef DEBUG
1388         xil_printf("\nData is %08x\r\n", Data);
1389 #endif
1390                 if (InstancePtr->RxBytes >= 4) {
1391                         (void)memcpy(Msg->RxBfrPtr, &Data, 4);
1392                         InstancePtr->RxBytes -= 4;
1393                         Msg->RxBfrPtr += 4;
1394                         Count += 4;
1395                 } else {
1396                         /* Read unaligned bytes (< 4 bytes) */
1397                         (void)memcpy(Msg->RxBfrPtr, &Data, InstancePtr->RxBytes);
1398                         Msg->RxBfrPtr += InstancePtr->RxBytes;
1399                         Count += InstancePtr->RxBytes;
1400                         InstancePtr->RxBytes = 0;
1401                 }
1402         }
1403 }
1404
1405 /*****************************************************************************/
1406 /**
1407 *
1408 * This function enables the polling functionality of controller
1409 *
1410 * @param        QspiPsuPtr is a pointer to the XQspiPsu instance.
1411 *
1412 * @param        Statuscommand is the status command which send by controller.
1413 *
1414 * @param        FlashMsg is a pointer to the structure containing transfer data
1415 *
1416 * @return       None
1417 *
1418 * @note         None.
1419 *
1420 ******************************************************************************/
1421 void XQspiPsu_PollData(XQspiPsu *QspiPsuPtr, XQspiPsu_Msg *FlashMsg)
1422 {
1423
1424         u32 GenFifoEntry ;
1425         u32 Value;
1426
1427         Xil_AssertVoid(QspiPsuPtr != NULL);
1428         Xil_AssertVoid(FlashMsg != NULL );
1429
1430         Value = XQspiPsu_Create_PollConfigData(QspiPsuPtr, FlashMsg);
1431         XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
1432                         XQSPIPSU_POLL_CFG_OFFSET, Value);
1433         XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
1434                         XQSPIPSU_P_TO_OFFSET, FlashMsg->PollTimeout);
1435
1436         XQspiPsu_Enable(QspiPsuPtr);
1437
1438         GenFifoEntry = (u32)0;
1439         GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_TX;
1440         GenFifoEntry |= QspiPsuPtr->GenFifoBus;
1441         GenFifoEntry |= QspiPsuPtr->GenFifoCS;
1442         GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
1443         GenFifoEntry |= (u32)FlashMsg->PollStatusCmd;
1444
1445         XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
1446                 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1447         XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
1448                                 (XQSPIPSU_CFG_START_GEN_FIFO_MASK
1449                                 | XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK));
1450
1451         GenFifoEntry = (u32)0;
1452         GenFifoEntry = (u32)XQSPIPSU_GENFIFO_POLL;
1453         GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_RX;
1454         GenFifoEntry |= QspiPsuPtr->GenFifoBus;
1455         GenFifoEntry |= QspiPsuPtr->GenFifoCS;
1456         GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
1457         if (((FlashMsg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != FALSE)
1458                 GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
1459         else
1460                 GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
1461
1462         XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
1463                 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1464
1465         QspiPsuPtr->Msg = FlashMsg;
1466         QspiPsuPtr->NumMsg = (s32)1;
1467         QspiPsuPtr->MsgCnt = 0;
1468
1469         Value = XQspiPsu_ReadReg(QspiPsuPtr->Config.BaseAddress,
1470                         XQSPIPSU_CFG_OFFSET);
1471         Value |= (XQSPIPSU_CFG_START_GEN_FIFO_MASK |
1472                         XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK |
1473                         XQSPIPSU_CFG_EN_POLL_TO_MASK);
1474         XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
1475                         Value);
1476
1477         /* Enable interrupts */
1478         Value = ((u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
1479                 (u32)XQSPIPSU_IER_TXEMPTY_MASK |
1480                 (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
1481                 (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
1482                 (u32)XQSPIPSU_IER_RXEMPTY_MASK |
1483                 (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
1484         XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET,
1485                         Value);
1486 }
1487
1488 /*****************************************************************************/
1489 /**
1490 *
1491 * This function creates Poll config register data to write
1492 *
1493 * @param        BusMask is mask to enable/disable upper/lower data bus masks.
1494 *
1495 * @param        DataBusMask is Data bus mask value during poll operation.
1496 *
1497 * @param        Data is the poll data value to write into config regsiter.
1498 *
1499 * @return       None
1500 *
1501 * @note         None.
1502 *
1503 ******************************************************************************/
1504 static inline u32 XQspiPsu_Create_PollConfigData(XQspiPsu *QspiPsuPtr,
1505                 XQspiPsu_Msg *FlashMsg)
1506 {
1507         u32 ConfigData = 0;
1508
1509         if (QspiPsuPtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_UPPER)
1510                 ConfigData = XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
1511                                    XQSPIPSU_POLL_CFG_EN_MASK_UPPER_SHIFT;
1512         if (QspiPsuPtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_LOWER)
1513                 ConfigData |= XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
1514                                    XQSPIPSU_POLL_CFG_EN_MASK_LOWER_SHIFT;
1515         ConfigData |= ((FlashMsg->PollBusMask << XQSPIPSU_POLL_CFG_MASK_EN_SHIFT)
1516                         & XQSPIPSU_POLL_CFG_MASK_EN_MASK);
1517         ConfigData |= ((FlashMsg->PollData << XQSPIPSU_POLL_CFG_DATA_VALUE_SHIFT)
1518                           & XQSPIPSU_POLL_CFG_DATA_VALUE_MASK);
1519         return ConfigData;
1520 }
1521
1522 /*****************************************************************************/
1523 /**
1524 * @brief
1525 * This API enables/ disables Write Protect pin on the flash parts.
1526 *
1527 * @param        QspiPtr is a pointer to the QSPIPSU driver component to use.
1528 *
1529 * @return       None
1530 *
1531 * @note By default WP pin as per the QSPI controller is driven High
1532 *               which means no write protection. Calling this function once
1533 *               will enable the protection.
1534 *
1535 ******************************************************************************/
1536 void XQspiPsu_WriteProtectToggle(XQspiPsu *QspiPsuPtr, u32 Toggle)
1537 {
1538         /* For Single and Stacked flash configuration with x1 or x2 mode*/
1539         if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_SINGLE) {
1540                 /* Enable */
1541                 XQspiPsu_Enable(QspiPsuPtr);
1542
1543                 /* Select slave */
1544                 XQspiPsu_GenFifoEntryCSAssert(QspiPsuPtr);
1545
1546                 XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_GPIO_OFFSET,
1547                                 Toggle);
1548
1549         } else if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL ||
1550                         QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_STACKED) {
1551                 xil_printf("Dual Parallel/Stacked configuration is not supported by this API\r\n");
1552         }
1553 }
1554 /** @} */