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_7
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.
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
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)
70 ******************************************************************************/
72 /***************************** Include Files *********************************/
76 /************************** Constant Definitions *****************************/
78 /**************************** Type Definitions *******************************/
80 /***************** Macros (Inline Functions) Definitions *********************/
82 /************************** Function Prototypes ******************************/
83 static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
85 static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode);
86 static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
88 static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
89 XQspiPsu_Msg *Msg, s32 Size);
90 static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
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);
103 /************************** Variable Definitions *****************************/
105 /*****************************************************************************/
108 * Initializes a specific XQspiPsu instance such that the driver is ready to use.
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.
125 * - XST_SUCCESS if successful.
126 * - XST_DEVICE_IS_STARTED if the device is already started.
127 * It must be stopped to re-initialize.
131 ******************************************************************************/
132 s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr, XQspiPsu_Config *ConfigPtr,
135 Xil_AssertNonvoid(InstancePtr != NULL);
136 Xil_AssertNonvoid(ConfigPtr != NULL);
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.
145 if (InstancePtr->IsBusy == TRUE) {
146 Status = (s32)XST_DEVICE_IS_STARTED;
149 /* Set some default values. */
150 InstancePtr->IsBusy = FALSE;
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;
172 XQspiPsu_Select(InstancePtr, XQSPIPSU_SEL_GQSPI_MASK);
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.
179 XQspiPsu_Reset(InstancePtr);
181 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
183 Status = XST_SUCCESS;
189 /*****************************************************************************/
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.
195 * The upper layer software is responsible for re-configuring (if necessary)
196 * and restarting the QSPIPSU device after the reset.
198 * @param InstancePtr is a pointer to the XQspiPsu instance.
204 ******************************************************************************/
205 void XQspiPsu_Reset(XQspiPsu *InstancePtr)
209 Xil_AssertVoid(InstancePtr != NULL);
211 /* Abort any transfer that is in progress */
212 XQspiPsu_Abort(InstancePtr);
214 /* Default value to config register */
215 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
216 XQSPIPSU_CFG_OFFSET);
219 ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
220 ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
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;
228 ConfigReg |= XQSPIPSU_CFG_WP_HOLD_MASK;
229 /* Clear prescalar by default */
230 ConfigReg &= (u32)(~XQSPIPSU_CFG_BAUD_RATE_DIV_MASK);
232 ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_PHA_MASK);
233 ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_POL_MASK);
235 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
236 XQSPIPSU_CFG_OFFSET, ConfigReg);
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);
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);
257 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
258 XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET,
259 XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL);
263 /*****************************************************************************/
266 * Aborts a transfer in progress by
268 * @param InstancePtr is a pointer to the XQspiPsu instance.
274 ******************************************************************************/
275 void XQspiPsu_Abort(XQspiPsu *InstancePtr)
278 u32 IntrStatus, ConfigReg;
280 IntrStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
281 XQSPIPSU_ISR_OFFSET);
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);
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);
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.
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);
322 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
323 XQSPIPSU_FIFO_CTRL_OFFSET,
324 XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK);
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);
333 /* Disable QSPIPSU */
334 XQspiPsu_Disable(InstancePtr);
336 InstancePtr->TxBytes = 0;
337 InstancePtr->RxBytes = 0;
338 InstancePtr->GenFifoEntries = 0;
339 InstancePtr->IsBusy = FALSE;
342 /*****************************************************************************/
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.
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.
353 * - XST_SUCCESS if successful.
354 * - XST_FAILURE if transfer fails.
355 * - XST_DEVICE_BUSY if a transfer is already in progress.
359 ******************************************************************************/
360 s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
365 u32 QspiPsuStatusReg;
368 u32 IOPending = (u32)FALSE;
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);
376 /* Check whether there is another transfer in progress. Not thread-safe */
377 if (InstancePtr->IsBusy == TRUE) {
378 return (s32)XST_DEVICE_BUSY;
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;
390 * Set the busy flag, which will be cleared when the transfer is
393 InstancePtr->IsBusy = TRUE;
395 BaseAddress = InstancePtr->Config.BaseAddress;
398 XQspiPsu_Enable(InstancePtr);
401 XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
405 while (Index < (s32)NumMsg) {
406 XQspiPsu_GenFifoEntryData(InstancePtr, Msg, Index);
408 if (InstancePtr->IsManualstart == TRUE) {
410 xil_printf("\nManual Start\r\n");
412 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
413 XQspiPsu_ReadReg(BaseAddress,
414 XQSPIPSU_CFG_OFFSET) |
415 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
418 /* Use thresholds here */
419 /* If there is more data to be transmitted */
421 QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
422 XQSPIPSU_ISR_OFFSET);
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],
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)) {
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,
442 /* Read remaining bytes using IO mode */
443 if((InstancePtr->RxBytes % 4) != 0 ) {
444 XQspiPsu_WriteReg(BaseAddress,
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;
458 InstancePtr->RxBytes = 0;
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)
467 XQspiPsu_ReadRxFifo(InstancePtr,
468 &Msg[Index], RxThr*4);
471 if ((QspiPsuStatusReg &
472 XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
473 XQspiPsu_ReadRxFifo(InstancePtr,
474 &Msg[Index], InstancePtr->RxBytes);
479 } while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) ||
480 (InstancePtr->TxBytes != 0) ||
481 ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == FALSE) ||
482 (InstancePtr->RxBytes != 0));
484 if((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
485 InstancePtr->IsUnaligned = 0;
486 XQspiPsu_WriteReg(BaseAddress,
487 XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
489 XQSPIPSU_CFG_OFFSET) |
490 XQSPIPSU_CFG_MODE_EN_DMA_MASK));
491 InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
494 if (IOPending == (u32)TRUE) {
495 IOPending = (u32)FALSE;
501 /* De-select slave */
502 XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
504 if (InstancePtr->IsManualstart == TRUE) {
506 xil_printf("\nManual Start\r\n");
508 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
509 XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
510 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
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);
519 /* Clear the busy flag. */
520 InstancePtr->IsBusy = FALSE;
522 /* Disable the device. */
523 XQspiPsu_Disable(InstancePtr);
528 /*****************************************************************************/
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.
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.
540 * - XST_SUCCESS if successful.
541 * - XST_FAILURE if transfer fails.
542 * - XST_DEVICE_BUSY if a transfer is already in progress.
546 ******************************************************************************/
547 s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
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);
560 /* Check whether there is another transfer in progress. Not thread-safe */
561 if (InstancePtr->IsBusy == TRUE) {
562 return (s32)XST_DEVICE_BUSY;
565 if (Msg[0].Flags & XQSPIPSU_MSG_FLAG_POLL) {
566 InstancePtr->IsBusy = TRUE;
567 XQspiPsu_PollData(InstancePtr, Msg);
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;
578 * Set the busy flag, which will be cleared when the transfer is
581 InstancePtr->IsBusy = TRUE;
583 BaseAddress = InstancePtr->Config.BaseAddress;
585 InstancePtr->Msg = Msg;
586 InstancePtr->NumMsg = (s32)NumMsg;
587 InstancePtr->MsgCnt = 0;
590 XQspiPsu_Enable(InstancePtr);
593 XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
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);
599 if (InstancePtr->IsManualstart == TRUE) {
601 xil_printf("\nManual Start\r\n");
603 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
604 XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
605 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
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);
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);
622 /*****************************************************************************/
625 * Handles interrupt based transfers by acting on GENFIFO and DMA interurpts.
627 * @param InstancePtr is a pointer to the XQspiPsu instance.
630 * - XST_SUCCESS if successful.
631 * - XST_FAILURE if transfer fails.
635 ******************************************************************************/
636 s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr)
638 u32 QspiPsuStatusReg, DmaIntrStatusReg = 0;
647 Xil_AssertNonvoid(InstancePtr != NULL);
649 BaseAddress = InstancePtr->Config.BaseAddress;
650 Msg = InstancePtr->Msg;
651 NumMsg = InstancePtr->NumMsg;
652 MsgCnt = InstancePtr->MsgCnt;
653 TxRxFlag = Msg[MsgCnt].Flags;
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);
662 XQspiPsu_WriteReg(BaseAddress,
663 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrStatusReg);
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);
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],
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.
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)) {
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,
708 if(InstancePtr->IsManualstart == TRUE) {
710 xil_printf("\nManual Start\r\n");
712 XQspiPsu_WriteReg(BaseAddress,
714 XQspiPsu_ReadReg(BaseAddress,
715 XQSPIPSU_CFG_OFFSET) |
716 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
720 InstancePtr->RxBytes = 0;
726 if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
727 if (InstancePtr->RxBytes != 0) {
728 if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
730 RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
731 XQSPIPSU_RX_THRESHOLD_OFFSET);
732 XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
735 if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
736 ((QspiPsuStatusReg & XQSPIPSU_ISR_RXEMPTY_MASK) == FALSE)) {
737 XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
738 InstancePtr->RxBytes);
741 if (InstancePtr->RxBytes == 0) {
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.
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)) {
763 InstancePtr->MsgCnt = MsgCnt;
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.
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;
782 /* This might not work if not manual start */
783 XQspiPsu_GenFifoEntryData(InstancePtr, Msg, MsgCnt);
785 if (InstancePtr->IsManualstart == TRUE) {
787 xil_printf("\nManual Start\r\n");
789 XQspiPsu_WriteReg(BaseAddress,
791 XQspiPsu_ReadReg(BaseAddress,
792 XQSPIPSU_CFG_OFFSET) |
793 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
795 } else if (MsgCnt == NumMsg) {
796 /* This is just to keep track of the de-assert entry */
798 InstancePtr->MsgCnt = MsgCnt;
800 /* De-select slave */
801 XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
803 if (InstancePtr->IsManualstart == TRUE) {
805 xil_printf("\nManual Start\r\n");
807 XQspiPsu_WriteReg(BaseAddress,
809 XQspiPsu_ReadReg(BaseAddress,
810 XQSPIPSU_CFG_OFFSET) |
811 XQSPIPSU_CFG_START_GEN_FIFO_MASK);
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);
827 /* Clear the busy flag. */
828 InstancePtr->IsBusy = FALSE;
830 /* Disable the device. */
831 XQspiPsu_Disable(InstancePtr);
833 /* Call status handler to indicate completion */
834 InstancePtr->StatusHandler(InstancePtr->StatusRef,
835 XST_SPI_TRANSFER_DONE, 0);
838 if ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) != FALSE){
839 if (QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK){
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.
845 XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_RXD_OFFSET);
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);
856 InstancePtr->IsBusy = FALSE;
857 /* Disable the device. */
858 XQspiPsu_Disable(InstancePtr);
861 if (QspiPsuStatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK){
862 InstancePtr->StatusHandler(InstancePtr->StatusRef,
863 XST_FLASH_TIMEOUT_ERROR, 0);
869 /*****************************************************************************/
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.
880 * XST_SPI_TRANSFER_DONE The requested data transfer is done
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.
889 * XST_SPI_RECEIVE_OVERRUN The QSPIPSU device lost data. Data was received
890 * but the receive data register/FIFO was full.
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.
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.
905 ******************************************************************************/
906 void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
907 XQspiPsu_StatusHandler FuncPointer)
909 Xil_AssertVoid(InstancePtr != NULL);
910 Xil_AssertVoid(FuncPointer != NULL);
911 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
913 InstancePtr->StatusHandler = FuncPointer;
914 InstancePtr->StatusRef = CallBackRef;
917 /*****************************************************************************/
920 * This is a stub for the status callback. The stub is here in case the upper
921 * layers forget to set the handler.
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
932 ******************************************************************************/
933 static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
940 Xil_AssertVoidAlways();
943 /*****************************************************************************/
946 * Selects SPI mode - x1 or x2 or x4.
948 * @param SpiMode - spi or dual or quad.
949 * @return Mask to set desired SPI mode in GENFIFO entry.
953 ******************************************************************************/
954 static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode)
959 xil_printf("\nXQspiPsu_SelectSpiMode\r\n");
963 case XQSPIPSU_SELECT_MODE_DUALSPI:
964 Mask = XQSPIPSU_GENFIFO_MODE_DUALSPI;
966 case XQSPIPSU_SELECT_MODE_QUADSPI:
967 Mask = XQSPIPSU_GENFIFO_MODE_QUADSPI;
969 case XQSPIPSU_SELECT_MODE_SPI:
970 Mask = XQSPIPSU_GENFIFO_MODE_SPI;
973 Mask = XQSPIPSU_GENFIFO_MODE_SPI;
977 xil_printf("\nSPIMode is %08x\r\n", SpiMode);
983 /*****************************************************************************/
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.
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
998 ******************************************************************************/
999 static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
1002 Xil_AssertVoid(InstancePtr != NULL);
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;
1020 if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) &&
1021 ((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == FALSE)) {
1023 *GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX;
1024 InstancePtr->TxBytes = 0;
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);
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;
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);
1064 /*****************************************************************************/
1067 * Fills the TX FIFO as long as there is room in the FIFO or the bytes required
1068 * to be transmitted.
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.
1078 ******************************************************************************/
1079 static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
1080 XQspiPsu_Msg *Msg, s32 Size)
1085 Xil_AssertVoid(InstancePtr != NULL);
1088 xil_printf("\nXQspiPsu_FillTxFifo\r\n");
1091 while ((InstancePtr->TxBytes > 0) && (Count < Size)) {
1092 if (InstancePtr->TxBytes >= 4) {
1093 (void)memcpy(&Data, Msg->TxBfrPtr, 4);
1095 InstancePtr->TxBytes -= 4;
1098 (void)memcpy(&Data, Msg->TxBfrPtr, InstancePtr->TxBytes);
1099 Msg->TxBfrPtr += InstancePtr->TxBytes;
1100 Count += InstancePtr->TxBytes;
1101 InstancePtr->TxBytes = 0;
1103 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1104 XQSPIPSU_TXD_OFFSET, Data);
1106 xil_printf("\nData is %08x\r\n", Data);
1110 if (InstancePtr->TxBytes < 0) {
1111 InstancePtr->TxBytes = 0;
1115 /*****************************************************************************/
1118 * This function sets up the RX DMA operation.
1120 * @param InstancePtr is a pointer to the XQspiPsu instance.
1121 * @param Msg is a pointer to the structure containing transfer data.
1127 ******************************************************************************/
1128 static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
1135 Xil_AssertVoid(InstancePtr != NULL);
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,
1145 AddrTemp = (u64)((INTPTR)(Msg->RxBfrPtr) >> 32);
1146 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1147 XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET,
1149 XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
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;
1159 if (InstancePtr->Config.IsCacheCoherent == 0) {
1160 Xil_DCacheInvalidateRange((INTPTR)InstancePtr->RecvBufferPtr,
1164 /* Write no. of words to DMA DST SIZE */
1165 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1166 XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
1170 /*****************************************************************************/
1173 * This function writes the GENFIFO entry to assert CS.
1175 * @param InstancePtr is a pointer to the XQspiPsu instance.
1181 ******************************************************************************/
1182 static inline void XQspiPsu_GenFifoEntryCSAssert(XQspiPsu *InstancePtr)
1187 xil_printf("\nXQspiPsu_GenFifoEntryCSAssert\r\n");
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;
1201 xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1203 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1204 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1207 /*****************************************************************************/
1210 * This function writes the GENFIFO entries to transmit the messages requested.
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.
1217 * - XST_SUCCESS if successful.
1218 * - XST_FAILURE if transfer fails.
1219 * - XST_DEVICE_BUSY if a transfer is already in progress.
1223 ******************************************************************************/
1224 static inline void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr,
1225 XQspiPsu_Msg *Msg, s32 Index)
1233 xil_printf("\nXQspiPsu_GenFifoEntryData\r\n");
1236 BaseAddress = InstancePtr->Config.BaseAddress;
1238 GenFifoEntry = 0x0U;
1240 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
1241 GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg[Index].BusWidth);
1243 GenFifoEntry |= InstancePtr->GenFifoCS;
1244 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
1245 GenFifoEntry |= InstancePtr->GenFifoBus;
1248 if (((Msg[Index].Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != FALSE) {
1249 GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
1251 GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
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;
1264 XQspiPsu_TXRXSetup(InstancePtr, &Msg[Index], &GenFifoEntry);
1266 if (Msg[Index].ByteCount < XQSPIPSU_GENFIFO_IMM_DATA_MASK) {
1267 GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
1268 GenFifoEntry |= Msg[Index].ByteCount;
1270 xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1272 XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
1275 TempCount = Msg[Index].ByteCount;
1276 u32 Exponent = 8; /* 2^8 = 256 */
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;
1286 xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1288 XQspiPsu_WriteReg(BaseAddress,
1289 XQSPIPSU_GEN_FIFO_OFFSET,
1292 TempCount = TempCount >> 1;
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;
1302 xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1304 XQspiPsu_WriteReg(BaseAddress,
1305 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
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;
1314 xil_printf("\nDummy FifoEntry=%08x\r\n",GenFifoEntry);
1316 XQspiPsu_WriteReg(BaseAddress,
1317 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1321 /*****************************************************************************/
1324 * This function writes the GENFIFO entry to de-assert CS.
1326 * @param InstancePtr is a pointer to the XQspiPsu instance.
1332 ******************************************************************************/
1333 static inline void XQspiPsu_GenFifoEntryCSDeAssert(XQspiPsu *InstancePtr)
1338 xil_printf("\nXQspiPsu_GenFifoEntryCSDeAssert\r\n");
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;
1351 xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
1353 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1354 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1357 /*****************************************************************************/
1360 * Read the specified number of bytes from RX FIFO
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.
1370 ******************************************************************************/
1371 static inline void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,
1372 XQspiPsu_Msg *Msg, s32 Size)
1378 xil_printf("\nXQspiPsu_ReadRxFifo\r\n");
1381 Xil_AssertVoid(InstancePtr != NULL);
1382 Xil_AssertVoid(Msg != NULL);
1384 while ((InstancePtr->RxBytes != 0) && (Count < Size)) {
1385 Data = XQspiPsu_ReadReg(InstancePtr->
1386 Config.BaseAddress, XQSPIPSU_RXD_OFFSET);
1388 xil_printf("\nData is %08x\r\n", Data);
1390 if (InstancePtr->RxBytes >= 4) {
1391 (void)memcpy(Msg->RxBfrPtr, &Data, 4);
1392 InstancePtr->RxBytes -= 4;
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;
1405 /*****************************************************************************/
1408 * This function enables the polling functionality of controller
1410 * @param QspiPsuPtr is a pointer to the XQspiPsu instance.
1412 * @param Statuscommand is the status command which send by controller.
1414 * @param FlashMsg is a pointer to the structure containing transfer data
1420 ******************************************************************************/
1421 void XQspiPsu_PollData(XQspiPsu *QspiPsuPtr, XQspiPsu_Msg *FlashMsg)
1427 Xil_AssertVoid(QspiPsuPtr != NULL);
1428 Xil_AssertVoid(FlashMsg != NULL );
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);
1436 XQspiPsu_Enable(QspiPsuPtr);
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;
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));
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;
1460 GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
1462 XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
1463 XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
1465 QspiPsuPtr->Msg = FlashMsg;
1466 QspiPsuPtr->NumMsg = (s32)1;
1467 QspiPsuPtr->MsgCnt = 0;
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,
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,
1488 /*****************************************************************************/
1491 * This function creates Poll config register data to write
1493 * @param BusMask is mask to enable/disable upper/lower data bus masks.
1495 * @param DataBusMask is Data bus mask value during poll operation.
1497 * @param Data is the poll data value to write into config regsiter.
1503 ******************************************************************************/
1504 static inline u32 XQspiPsu_Create_PollConfigData(XQspiPsu *QspiPsuPtr,
1505 XQspiPsu_Msg *FlashMsg)
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);
1522 /*****************************************************************************/
1525 * This API enables/ disables Write Protect pin on the flash parts.
1527 * @param QspiPtr is a pointer to the QSPIPSU driver component to use.
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.
1535 ******************************************************************************/
1536 void XQspiPsu_WriteProtectToggle(XQspiPsu *QspiPsuPtr, u32 Toggle)
1538 /* For Single and Stacked flash configuration with x1 or x2 mode*/
1539 if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_SINGLE) {
1541 XQspiPsu_Enable(QspiPsuPtr);
1544 XQspiPsu_GenFifoEntryCSAssert(QspiPsuPtr);
1546 XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_GPIO_OFFSET,
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");