]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A53_64-bit_UltraScale_MPSoC/RTOSDemo_A53_bsp/psu_cortexa53_0/libsrc/qspipsu_v1_3/src/xqspipsu_options.c
Update Zynq MPSoC hardware definition and BSP files to be those shipped with the...
[freertos] / FreeRTOS / Demo / CORTEX_A53_64-bit_UltraScale_MPSoC / RTOSDemo_A53_bsp / psu_cortexa53_0 / libsrc / qspipsu_v1_3 / src / xqspipsu_options.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_options.c
36 * @addtogroup qspipsu_v1_0
37 * @{
38 *
39 * This file implements funcitons to configure the QSPIPSU component,
40 * specifically some optional settings, clock and flash related information.
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 *       sk  04/24/15 Modified the code according to MISRAC-2012.
50 * 1.1   sk  04/12/16 Added debug message prints.
51 * 1.2   nsk 07/01/16 Modified XQspiPsu_SetOptions() to support
52 *                    LQSPI options and updated OptionsTable
53 *       rk  07/15/16 Added support for TapDelays at different frequencies.
54 *
55 * </pre>
56 *
57 ******************************************************************************/
58
59 /***************************** Include Files *********************************/
60
61 #include "xqspipsu.h"
62
63 /************************** Constant Definitions *****************************/
64
65 /**************************** Type Definitions *******************************/
66
67 /***************** Macros (Inline Functions) Definitions *********************/
68
69 #if defined (ARMR5) || (__aarch64__)
70 #define TAPDLY_BYPASS_VALVE_40MHZ 0x01
71 #define TAPDLY_BYPASS_VALVE_100MHZ 0x01
72 #define USE_DLY_LPBK  0x01
73 #define USE_DATA_DLY_ADJ 0x01
74 #define DATA_DLY_ADJ_DLY 0X02
75 #define LPBK_DLY_ADJ_DLY0 0X02
76 #endif
77
78 /************************** Function Prototypes ******************************/
79
80 #if defined (ARMR5) || (__aarch64__)
81 s32 XQspi_Set_TapDelay(XQspiPsu * InstancePtr,u32 TapdelayBypass,
82                                                 u32 LPBKDelay,u32 Datadelay);
83 static s32 XQspipsu_Calculate_Tapdelay(XQspiPsu *InstancePtr, u8 Prescaler);
84 #endif
85
86 /************************** Variable Definitions *****************************/
87
88 /*
89  * Create the table of options which are processed to get/set the device
90  * options. These options are table driven to allow easy maintenance and
91  * expansion of the options.
92  */
93 typedef struct {
94         u32 Option;
95         u32 Mask;
96 } OptionsMap;
97
98 static OptionsMap OptionsTable[] = {
99         {XQSPIPSU_CLK_ACTIVE_LOW_OPTION, XQSPIPSU_CFG_CLK_POL_MASK},
100         {XQSPIPSU_CLK_PHASE_1_OPTION, XQSPIPSU_CFG_CLK_PHA_MASK},
101         {XQSPIPSU_MANUAL_START_OPTION, XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK},
102         {XQSPIPSU_LQSPI_MODE_OPTION, XQSPIPSU_CFG_WP_HOLD_MASK},
103 };
104
105 #define XQSPIPSU_NUM_OPTIONS    (sizeof(OptionsTable) / sizeof(OptionsMap))
106
107 /*****************************************************************************/
108 /**
109 *
110 * This function sets the options for the QSPIPSU device driver.The options
111 * control how the device behaves relative to the QSPIPSU bus. The device must be
112 * idle rather than busy transferring data before setting these device options.
113 *
114 * @param        InstancePtr is a pointer to the XQspiPsu instance.
115 * @param        Options contains the specified options to be set. This is a bit
116 *               mask where a 1 indicates the option should be turned ON and
117 *               a 0 indicates no action. One or more bit values may be
118 *               contained in the mask. See the bit definitions named
119 *               XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
120 *
121 * @return
122 *               - XST_SUCCESS if options are successfully set.
123 *               - XST_DEVICE_BUSY if the device is currently transferring data.
124 *               The transfer must complete or be aborted before setting options.
125 *
126 * @note
127 * This function is not thread-safe.
128 *
129 ******************************************************************************/
130 s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options)
131 {
132         u32 ConfigReg;
133         u32 Index;
134         u32 QspiPsuOptions;
135         s32 Status;
136
137         Xil_AssertNonvoid(InstancePtr != NULL);
138         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
139
140         /*
141          * Do not allow to modify the Control Register while a transfer is in
142          * progress. Not thread-safe.
143          */
144         if (InstancePtr->IsBusy == TRUE) {
145                 Status = (s32)XST_DEVICE_BUSY;
146         } else {
147
148                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
149                                               XQSPIPSU_CFG_OFFSET);
150                 QspiPsuOptions = Options & XQSPIPSU_LQSPI_MODE_OPTION;
151                 Options &= ~XQSPIPSU_LQSPI_MODE_OPTION;
152                 /*
153                  * Loop through the options table, turning the option on
154                  * depending on whether the bit is set in the incoming options flag.
155                  */
156                 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
157                         if ((Options & OptionsTable[Index].Option) != FALSE) {
158                                 /* Turn it on */
159                                 ConfigReg |= OptionsTable[Index].Mask;
160                         } else {
161                 /* Turn it off */
162                 ConfigReg &= ~(OptionsTable[Index].Mask);
163         }
164
165                 }
166                 /*
167                  * Now write the control register. Leave it to the upper layers
168                  * to restart the device.
169                  */
170                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
171                                  ConfigReg);
172
173                 if ((Options & XQSPIPSU_MANUAL_START_OPTION) != FALSE) {
174                         InstancePtr->IsManualstart = TRUE;
175                 }
176                 /*
177                  * Check for the LQSPI configuration options.
178                  */
179                 ConfigReg = XQspiPsu_ReadReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET);
180
181                         if (QspiPsuOptions & XQSPIPSU_LQSPI_MODE_OPTION) {
182                         XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET,XQSPIPS_LQSPI_CR_RST_STATE);
183                         XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_CFG_OFFSET,XQSPIPS_LQSPI_CFG_RST_STATE);
184                         /* Enable the QSPI controller */
185                         XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_EN_OFFSET,XQSPIPSU_EN_MASK);
186                 }
187                  else {
188                         ConfigReg &= ~(XQSPIPSU_LQSPI_CR_LINEAR_MASK);
189                         XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET, ConfigReg);
190                 }
191
192                 Status = XST_SUCCESS;
193         }
194
195         return Status;
196 }
197
198 /*****************************************************************************/
199 /**
200 *
201 * This function resets the options for the QSPIPSU device driver.The options
202 * control how the device behaves relative to the QSPIPSU bus. The device must be
203 * idle rather than busy transferring data before setting these device options.
204 *
205 * @param        InstancePtr is a pointer to the XQspiPsu instance.
206 * @param        Options contains the specified options to be set. This is a bit
207 *               mask where a 1 indicates the option should be turned OFF and
208 *               a 0 indicates no action. One or more bit values may be
209 *               contained in the mask. See the bit definitions named
210 *               XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
211 *
212 * @return
213 *               - XST_SUCCESS if options are successfully set.
214 *               - XST_DEVICE_BUSY if the device is currently transferring data.
215 *               The transfer must complete or be aborted before setting options.
216 *
217 * @note
218 * This function is not thread-safe.
219 *
220 ******************************************************************************/
221 s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options)
222 {
223         u32 ConfigReg;
224         u32 Index;
225         s32 Status;
226
227         Xil_AssertNonvoid(InstancePtr != NULL);
228         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
229
230         /*
231          * Do not allow to modify the Control Register while a transfer is in
232          * progress. Not thread-safe.
233          */
234         if (InstancePtr->IsBusy == TRUE) {
235                 Status = (s32)XST_DEVICE_BUSY;
236         } else {
237
238                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
239                                               XQSPIPSU_CFG_OFFSET);
240
241                 /*
242                  * Loop through the options table, turning the option on
243                  * depending on whether the bit is set in the incoming options flag.
244                  */
245                 for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
246                         if ((Options & OptionsTable[Index].Option) != FALSE) {
247                                 /* Turn it off */
248                                 ConfigReg &= ~OptionsTable[Index].Mask;
249                         }
250                 }
251
252                 /*
253                  * Now write the control register. Leave it to the upper layers
254                  * to restart the device.
255                  */
256                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
257                                  ConfigReg);
258
259                 if ((Options & XQSPIPSU_MANUAL_START_OPTION) != FALSE) {
260                         InstancePtr->IsManualstart = FALSE;
261                 }
262
263                 Status = XST_SUCCESS;
264         }
265
266         return Status;
267 }
268
269 /*****************************************************************************/
270 /**
271 *
272 * This function gets the options for the QSPIPSU device. The options control how
273 * the device behaves relative to the QSPIPSU bus.
274 *
275 * @param        InstancePtr is a pointer to the XQspiPsu instance.
276 *
277 * @return
278 *
279 * Options contains the specified options currently set. This is a bit value
280 * where a 1 means the option is on, and a 0 means the option is off.
281 * See the bit definitions named XQSPIPSU_*_OPTIONS in file xqspipsu.h.
282 *
283 * @note         None.
284 *
285 ******************************************************************************/
286 u32 XQspiPsu_GetOptions(XQspiPsu *InstancePtr)
287 {
288         u32 OptionsFlag = 0;
289         u32 ConfigReg;
290         u32 Index;
291
292         Xil_AssertNonvoid(InstancePtr != NULL);
293         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
294
295         /*
296          * Get the current options from QSPIPSU configuration register.
297          */
298         ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
299                                       XQSPIPSU_CFG_OFFSET);
300
301         /* Loop through the options table to grab options */
302         for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
303                 if ((ConfigReg & OptionsTable[Index].Mask) != FALSE) {
304                         OptionsFlag |= OptionsTable[Index].Option;
305                 }
306         }
307
308         return OptionsFlag;
309 }
310
311 #if defined (ARMR5) || (__aarch64__)
312 /*****************************************************************************/
313 /**
314 *
315 * This function sets the Tapdelay values for the QSPIPSU device driver.The device
316 * must be idle rather than busy transferring data before setting Tapdelay.
317 *
318 * @param        InstancePtr is a pointer to the XQspiPsu instance.
319 * @param        TapdelayBypss contains the IOU_TAPDLY_BYPASS register value.
320 * @param        LPBKDelay contains the GQSPI_LPBK_DLY_ADJ register value.
321 * @param        Datadelay contains the QSPI_DATA_DLY_ADJ register value.
322 *
323 * @return
324 *               - XST_SUCCESS if options are successfully set.
325 *               - XST_DEVICE_BUSY if the device is currently transferring data.
326 *               The transfer must complete or be aborted before setting TapDelay.
327 *
328 * @note
329 * This function is not thread-safe.
330 *
331 ******************************************************************************/
332 s32 XQspi_Set_TapDelay(XQspiPsu * InstancePtr,u32 TapdelayBypass,
333                                                 u32 LPBKDelay,u32 Datadelay)
334 {
335         s32 Status;
336
337         Xil_AssertNonvoid(InstancePtr != NULL);
338         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
339
340         /*
341          * Do not allow to modify the Control Register while a transfer is in
342          * progress. Not thread-safe.
343          */
344         if (InstancePtr->IsBusy == TRUE) {
345                 Status = XST_DEVICE_BUSY;
346         } else {
347                 XQspiPsu_WriteReg(XPS_SYS_CTRL_BASEADDR,IOU_TAPDLY_BYPASS_OFFSET,
348                                 TapdelayBypass);
349                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
350                                 XQSPIPSU_LPBK_DLY_ADJ_OFFSET,LPBKDelay);
351                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
352                                 XQSPIPSU_DATA_DLY_ADJ_OFFSET,Datadelay);
353                 Status = XST_SUCCESS;
354         }
355         return Status;
356 }
357
358 /*****************************************************************************/
359 /**
360 *
361 * Configures the clock according to the prescaler passed.
362 *
363 *
364 * @param        InstancePtr is a pointer to the XQspiPsu instance.
365 * @param        Prescaler - clock prescaler.
366 *
367 * @return
368 *               - XST_SUCCESS if successful.
369 *               - XST_DEVICE_BUSY if the device is currently transferring data.
370 *               The transfer must complete or be aborted before setting Tapdelay.
371 *
372 * @note         None.
373 *
374 ******************************************************************************/
375 static s32 XQspipsu_Calculate_Tapdelay(XQspiPsu *InstancePtr, u8 Prescaler)
376 {
377         u32 FreqDiv, Divider, Tapdelay, LBkModeReg, delayReg;
378         s32 Status;
379
380         Divider = (1 << (Prescaler+1));
381
382         FreqDiv = (InstancePtr->Config.InputClockHz)/Divider;
383         Tapdelay = XQspiPsu_ReadReg(XPS_SYS_CTRL_BASEADDR,
384                                         IOU_TAPDLY_BYPASS_OFFSET);
385
386         Tapdelay = Tapdelay & (~IOU_TAPDLY_BYPASS_LQSPI_RX_MASK);
387
388         LBkModeReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
389                         XQSPIPSU_LPBK_DLY_ADJ_OFFSET);
390
391         LBkModeReg = (LBkModeReg &
392                         (~(XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK))) &
393                         (LBkModeReg & (~(XQSPIPSU_LPBK_DLY_ADJ_DLY1_MASK))) &
394                         (LBkModeReg & (~(XQSPIPSU_LPBK_DLY_ADJ_DLY0_MASK)));
395
396         delayReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
397                         XQSPIPSU_DATA_DLY_ADJ_OFFSET);
398
399         delayReg = (delayReg &
400                         (~(XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_MASK))) &
401                         (delayReg & (~( XQSPIPSU_DATA_DLY_ADJ_DLY_MASK)));
402
403         if(FreqDiv < XQSPIPSU_FREQ_40MHZ){
404                 Tapdelay = Tapdelay |
405                                 (TAPDLY_BYPASS_VALVE_40MHZ << IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
406         } else if (FreqDiv <= XQSPIPSU_FREQ_100MHZ) {
407                 Tapdelay = Tapdelay | (TAPDLY_BYPASS_VALVE_100MHZ << IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
408                 LBkModeReg = LBkModeReg |
409                                 (USE_DLY_LPBK <<  XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT);
410                 delayReg = delayReg |
411                                 (USE_DATA_DLY_ADJ  << XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT) |
412                                 (DATA_DLY_ADJ_DLY  << XQSPIPSU_DATA_DLY_ADJ_DLY_SHIFT);
413         } else if (FreqDiv <= XQSPIPSU_FREQ_150MHZ) {
414                 LBkModeReg = LBkModeReg |
415                                 (USE_DLY_LPBK  <<  XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT ) |
416                                 (LPBK_DLY_ADJ_DLY0  << XQSPIPSU_LPBK_DLY_ADJ_DLY0_SHIFT);
417         }
418         Status = XQspi_Set_TapDelay(InstancePtr, Tapdelay, LBkModeReg, delayReg);
419
420         return Status;
421 }
422 #endif
423
424 /*****************************************************************************/
425 /**
426 *
427 * Configures the clock according to the prescaler passed.
428 *
429 *
430 * @param        InstancePtr is a pointer to the XQspiPsu instance.
431 * @param        Prescaler - clock prescaler to be set.
432 *
433 * @return
434 *               - XST_SUCCESS if successful.
435 *               - XST_DEVICE_IS_STARTED if the device is already started.
436 *               - XST_DEVICE_BUSY if the device is currently transferring data.
437 *               It must be stopped to re-initialize.
438 *
439 * @note         None.
440 *
441 ******************************************************************************/
442 s32 XQspiPsu_SetClkPrescaler(XQspiPsu *InstancePtr, u8 Prescaler)
443 {
444         u32 ConfigReg;
445         s32 Status;
446
447         Xil_AssertNonvoid(InstancePtr != NULL);
448         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
449         Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
450
451         /*
452          * Do not allow the slave select to change while a transfer is in
453          * progress. Not thread-safe.
454          */
455         if (InstancePtr->IsBusy == TRUE) {
456                 Status = (s32)XST_DEVICE_BUSY;
457         } else {
458
459                 /*
460                  * Read the configuration register, mask out the relevant bits, and set
461                  * them with the shifted value passed into the function. Write the
462                  * results back to the configuration register.
463                  */
464                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
465                                               XQSPIPSU_CFG_OFFSET);
466
467                 ConfigReg &= (u32)(~XQSPIPSU_CFG_BAUD_RATE_DIV_MASK);
468                 ConfigReg |= (u32) ((u32)Prescaler & (u32)XQSPIPSU_CR_PRESC_MAXIMUM) <<
469                                     XQSPIPSU_CFG_BAUD_RATE_DIV_SHIFT;
470
471                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
472                                   XQSPIPSU_CFG_OFFSET, ConfigReg);
473
474 #if defined (ARMR5) || (__aarch64__)
475                 Status = XQspipsu_Calculate_Tapdelay(InstancePtr,Prescaler);
476 #else
477                 Status = XST_SUCCESS;
478 #endif
479         }
480
481         return Status;
482 }
483
484 /*****************************************************************************/
485 /**
486 *
487 * This funciton should be used to tell the QSPIPSU driver the HW flash
488 * configuration being used. This API should be called atleast once in the
489 * application. If desired, it can be called multiple times when switching
490 * between communicating to different flahs devices/using different configs.
491 *
492 * @param        InstancePtr is a pointer to the XQspiPsu instance.
493 * @param        FlashCS - Flash Chip Select.
494 * @param        FlashBus - Flash Bus (Upper, Lower or Both).
495 *
496 * @return
497 *               - XST_SUCCESS if successful.
498 *               - XST_DEVICE_IS_STARTED if the device is already started.
499 *               It must be stopped to re-initialize.
500 *
501 * @note         If this funciton is not called atleast once in the application,
502 *               the driver assumes there is a single flash connected to the
503 *               lower bus and CS line.
504 *
505 ******************************************************************************/
506 void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus)
507 {
508         Xil_AssertVoid(InstancePtr != NULL);
509
510 #ifdef DEBUG
511         xil_printf("\nXQspiPsu_SelectFlash\r\n");
512 #endif
513
514         /*
515          * Bus and CS lines selected here will be updated in the instance and
516          * used for subsequent GENFIFO entries during transfer.
517          */
518
519         /* Choose slave select line */
520         switch (FlashCS) {
521                 case XQSPIPSU_SELECT_FLASH_CS_BOTH:
522                         InstancePtr->GenFifoCS = (u32)XQSPIPSU_GENFIFO_CS_LOWER |
523                                                 (u32)XQSPIPSU_GENFIFO_CS_UPPER;
524                         break;
525                 case XQSPIPSU_SELECT_FLASH_CS_UPPER:
526                         InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_UPPER;
527                         break;
528                 case XQSPIPSU_SELECT_FLASH_CS_LOWER:
529                         InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
530                         break;
531                 default:
532                         InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
533                         break;
534         }
535
536         /* Choose bus */
537         switch (FlashBus) {
538                 case XQSPIPSU_SELECT_FLASH_BUS_BOTH:
539                         InstancePtr->GenFifoBus = (u32)XQSPIPSU_GENFIFO_BUS_LOWER |
540                                                 (u32)XQSPIPSU_GENFIFO_BUS_UPPER;
541                         break;
542                 case XQSPIPSU_SELECT_FLASH_BUS_UPPER:
543                         InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_UPPER;
544                         break;
545                 case XQSPIPSU_SELECT_FLASH_BUS_LOWER:
546                         InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
547                         break;
548                 default:
549                         InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
550                         break;
551         }
552 #ifdef DEBUG
553         xil_printf("\nGenFifoCS is %08x and GenFifoBus is %08x\r\n",
554                                 InstancePtr->GenFifoCS, InstancePtr->GenFifoBus);
555 #endif
556
557 }
558
559 /*****************************************************************************/
560 /**
561 *
562 * This function sets the Read mode for the QSPIPSU device driver.The device
563 * must be idle rather than busy transferring data before setting Read mode
564 * options.
565 *
566 * @param        InstancePtr is a pointer to the XQspiPsu instance.
567 * @param        Mode contains the specified Mode to be set. See the
568 *               bit definitions named XQSPIPSU_READMODE_* in the file xqspipsu.h.
569 *
570 * @return
571 *               - XST_SUCCESS if options are successfully set.
572 *               - XST_DEVICE_BUSY if the device is currently transferring data.
573 *               The transfer must complete or be aborted before setting Mode.
574 *
575 * @note
576 * This function is not thread-safe.
577 *
578 ******************************************************************************/
579 s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode)
580 {
581         u32 ConfigReg;
582         s32 Status;
583
584 #ifdef DEBUG
585         xil_printf("\nXQspiPsu_SetReadMode\r\n");
586 #endif
587
588         Xil_AssertNonvoid(InstancePtr != NULL);
589         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
590
591         /*
592          * Do not allow to modify the Control Register while a transfer is in
593          * progress. Not thread-safe.
594          */
595         if (InstancePtr->IsBusy == TRUE) {
596                 Status = (s32)XST_DEVICE_BUSY;
597         } else {
598
599                 InstancePtr->ReadMode = Mode;
600
601                 ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
602                                               XQSPIPSU_CFG_OFFSET);
603
604                 if (Mode == XQSPIPSU_READMODE_DMA) {
605                         ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
606                         ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
607                 } else {
608                         ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
609                 }
610
611                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
612                                  ConfigReg);
613
614                 Status = XST_SUCCESS;
615         }
616 #ifdef DEBUG
617         xil_printf("\nRead Mode is %08x\r\n", InstancePtr->ReadMode);
618 #endif
619         return Status;
620 }
621 /** @} */