1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_qspi.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.qspi"
14 #endif
15 
16 /*******************************************************************************
17  * Definitations
18  ******************************************************************************/
19 enum _qspi_transfer_state
20 {
21     kQSPI_TxBusy = 0x0U, /*!< QSPI is busy */
22     kQSPI_TxIdle,        /*!< Transfer is done. */
23     kQSPI_TxError        /*!< Transfer error occurred. */
24 };
25 
26 #define QSPI_AHB_BUFFER_REG(base, index) (((volatile uint32_t *)&((base)->BUF0CR))[(index)])
27 
28 #if (!defined(FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG)) || !FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG
29 #ifndef QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK
30 #define QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK (0x100U)
31 #endif
32 
33 #ifndef QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK
34 #define QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK (0x200U)
35 #endif
36 
37 #ifndef QuadSPI_SOCCR_DQS_PHASE_SEL_MASK
38 #define QuadSPI_SOCCR_DQS_PHASE_SEL_MASK  (0xC00U)
39 #define QuadSPI_SOCCR_DQS_PHASE_SEL_SHIFT (10U)
40 #define QuadSPI_SOCCR_DQS_PHASE_SEL(x) \
41     (((uint32_t)(((uint32_t)(x)) << QuadSPI_SOCCR_DQS_PHASE_SEL_SHIFT)) & QuadSPI_SOCCR_DQS_PHASE_SEL_MASK)
42 #endif
43 
44 #ifndef QuadSPI_SOCCR_DQS_INV_EN_MASK
45 #define QuadSPI_SOCCR_DQS_INV_EN_MASK  (0x1000U)
46 #define QuadSPI_SOCCR_DQS_INV_EN_SHIFT (12U)
47 #define QuadSPI_SOCCR_DQS_INV_EN(x) \
48     (((uint32_t)(((uint32_t)(x)) << QuadSPI_SOCCR_DQS_INV_EN_SHIFT)) & QuadSPI_SOCCR_DQS_INV_EN_MASK)
49 #endif
50 
51 #ifndef QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK
52 #define QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK  (0x7F0000U)
53 #define QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_SHIFT (16U)
54 #define QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL(x)                                    \
55     (((uint32_t)(((uint32_t)(x)) << QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_SHIFT)) & \
56      QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK)
57 #endif
58 #endif /* FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG */
59 
60 /*******************************************************************************
61  * Prototypes
62  ******************************************************************************/
63 
64 /*******************************************************************************
65  * Variables
66  ******************************************************************************/
67 /* Base pointer array */
68 static QuadSPI_Type *const s_qspiBases[] = QuadSPI_BASE_PTRS;
69 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
70 /* Clock name array */
71 static const clock_ip_name_t s_qspiClock[] = QSPI_CLOCKS;
72 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
73 
74 /*******************************************************************************
75  * Code
76  ******************************************************************************/
77 /*!
78  * brief Get the instance number for QSPI.
79  *
80  * param base QSPI base pointer.
81  */
QSPI_GetInstance(QuadSPI_Type * base)82 uint32_t QSPI_GetInstance(QuadSPI_Type *base)
83 {
84     uint32_t instance;
85 
86     /* Find the instance index from base address mappings. */
87     for (instance = 0; instance < ARRAY_SIZE(s_qspiBases); instance++)
88     {
89         if (s_qspiBases[instance] == base)
90         {
91             break;
92         }
93     }
94 
95     assert(instance < ARRAY_SIZE(s_qspiBases));
96 
97     return instance;
98 }
99 
100 /*!
101  * brief Initializes the QSPI module and internal state.
102  *
103  * This function enables the clock for QSPI and also configures the QSPI with the
104  * input configure parameters. Users should call this function before any QSPI operations.
105  *
106  * param base Pointer to QuadSPI Type.
107  * param config QSPI configure structure.
108  * param srcClock_Hz QSPI source clock frequency in Hz.
109  */
QSPI_Init(QuadSPI_Type * base,qspi_config_t * config,uint32_t srcClock_Hz)110 void QSPI_Init(QuadSPI_Type *base, qspi_config_t *config, uint32_t srcClock_Hz)
111 {
112     uint32_t i   = 0;
113     uint32_t val = 0;
114 
115 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
116     /* Enable QSPI clock */
117     CLOCK_EnableClock(s_qspiClock[QSPI_GetInstance(base)]);
118 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
119 
120     /* Do software reset to QSPI module */
121     QSPI_SoftwareReset(base);
122 
123     /* Clear the FIFO region */
124     QSPI_ClearFifo(base, (uint32_t)kQSPI_AllFifo);
125 
126     /* Configure QSPI */
127     QSPI_Enable(base, false);
128 
129 #if !defined(FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL) || (!FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL)
130     /* Set qspi clock source */
131     base->SOCCR = config->clockSource;
132 
133     /* Read MCR value, mask SCLKCFG field */
134     val = base->MCR;
135     val &= ~QuadSPI_MCR_SCLKCFG_MASK;
136 
137     /* To avoid the configured baudrate exceeds the expected baudrate value, which may possibly put the
138     QSPI work under unsupported frequency, set the divider higher when there is reminder, use ceiling
139     operation, ceiling(a/b) = (a-1)/b + 1. */
140     val |= QuadSPI_MCR_SCLKCFG((srcClock_Hz - 1U) / config->baudRate);
141     base->MCR = val;
142 #endif /* FSL_FEATURE_QSPI_CLOCK_CONTROL_EXTERNAL */
143 
144     /* Set AHB buffer size and buffer master */
145     for (i = 0; i < (uint32_t)FSL_FEATURE_QSPI_AHB_BUFFER_COUNT; i++)
146     {
147         val = QuadSPI_BUF0CR_MSTRID(config->AHBbufferMaster[i]) | QuadSPI_BUF0CR_ADATSZ(config->AHBbufferSize[i] / 8U);
148         QSPI_AHB_BUFFER_REG(base, i) = val;
149     }
150     if (config->enableAHBbuffer3AllMaster)
151     {
152         base->BUF3CR |= QuadSPI_BUF3CR_ALLMST_MASK;
153     }
154     else
155     {
156         base->BUF3CR &= ~QuadSPI_BUF3CR_ALLMST_MASK;
157     }
158 
159     /* Set watermark */
160     base->RBCT &= ~QuadSPI_RBCT_WMRK_MASK;
161     base->RBCT |= QuadSPI_RBCT_WMRK((uint32_t)config->rxWatermark - 1U);
162 
163 #if !defined(FSL_FEATURE_QSPI_HAS_NO_TXDMA) || (!FSL_FEATURE_QSPI_HAS_NO_TXDMA)
164     base->TBCT &= ~QuadSPI_TBCT_WMRK_MASK;
165     base->TBCT |= QuadSPI_TBCT_WMRK((uint32_t)config->txWatermark - 1U);
166 #endif /* FSL_FEATURE_QSPI_HAS_NO_TXDMA */
167 
168     /* Enable QSPI module */
169     if (config->enableQspi)
170     {
171         QSPI_Enable(base, true);
172     }
173 }
174 
175 /*!
176  * brief Gets default settings for QSPI.
177  *
178  * param config QSPI configuration structure.
179  */
QSPI_GetDefaultQspiConfig(qspi_config_t * config)180 void QSPI_GetDefaultQspiConfig(qspi_config_t *config)
181 {
182     /* Initializes the configure structure to zero. */
183     (void)memset(config, 0, sizeof(*config));
184 
185     config->clockSource               = 2U;
186     config->baudRate                  = 24000000U;
187     config->AHBbufferMaster[0]        = 0xE;
188     config->AHBbufferMaster[1]        = 0xE;
189     config->AHBbufferMaster[2]        = 0xE;
190     config->enableAHBbuffer3AllMaster = true;
191     config->txWatermark               = 8U;
192     config->rxWatermark               = 8U;
193     config->enableQspi                = true;
194 }
195 
196 /*!
197  * brief Deinitializes the QSPI module.
198  *
199  * Clears the QSPI state and  QSPI module registers.
200  * param base Pointer to QuadSPI Type.
201  */
QSPI_Deinit(QuadSPI_Type * base)202 void QSPI_Deinit(QuadSPI_Type *base)
203 {
204     QSPI_Enable(base, false);
205 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
206     CLOCK_DisableClock(s_qspiClock[QSPI_GetInstance(base)]);
207 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
208 }
209 
210 /*!
211  * brief Configures the serial flash parameter.
212  *
213  * This function configures the serial flash relevant parameters, such as the size, command, and so on.
214  * The flash configuration value cannot have a default value. The user needs to configure it according to the
215  * QSPI features.
216  *
217  * param base Pointer to QuadSPI Type.
218  * param config Flash configuration parameters.
219  */
QSPI_SetFlashConfig(QuadSPI_Type * base,qspi_flash_config_t * config)220 void QSPI_SetFlashConfig(QuadSPI_Type *base, qspi_flash_config_t *config)
221 {
222     uint32_t address = FSL_FEATURE_QSPI_AMBA_BASE + config->flashA1Size;
223     uint32_t val     = 0;
224     uint32_t i       = 0;
225 
226     /* Disable module */
227     QSPI_Enable(base, false);
228 
229     /* Config the serial flash size */
230     base->SFA1AD = address;
231     address += config->flashA2Size;
232     base->SFA2AD = address;
233 #if defined(FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE) && (FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE)
234     address += config->flashB1Size;
235     base->SFB1AD = address;
236     address += config->flashB2Size;
237     base->SFB2AD = address;
238 #endif /* FSL_FEATURE_QSPI_SUPPORT_PARALLEL_MODE */
239 
240 #if !defined(FSL_FEATURE_QSPI_HAS_NO_SFACR) || (!FSL_FEATURE_QSPI_HAS_NO_SFACR)
241     /* Set Word Addressable feature */
242     val         = QuadSPI_SFACR_WA(config->enableWordAddress) | QuadSPI_SFACR_CAS(config->cloumnspace);
243     base->SFACR = val;
244 #endif /* FSL_FEATURE_QSPI_HAS_NO_SFACR */
245 
246     /* Config look up table */
247     base->LUTKEY = 0x5AF05AF0U;
248     base->LCKCR  = 0x2U;
249     for (i = 0; i < (uint32_t)FSL_FEATURE_QSPI_LUT_DEPTH; i++)
250     {
251         base->LUT[i] = config->lookuptable[i];
252     }
253     base->LUTKEY = 0x5AF05AF0U;
254     base->LCKCR  = 0x1U;
255 
256 #if !defined(FSL_FEATURE_QSPI_HAS_NO_TDH) || (!FSL_FEATURE_QSPI_HAS_NO_TDH)
257     /* Config flash timing */
258     val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TDH(config->dataHoldTime) |
259           QuadSPI_FLSHCR_TCSH(config->CSSetupTime);
260 #else
261     val = QuadSPI_FLSHCR_TCSS(config->CSHoldTime) | QuadSPI_FLSHCR_TCSH(config->CSSetupTime);
262 #endif /* FSL_FEATURE_QSPI_HAS_NO_TDH */
263     base->FLSHCR = val;
264 
265     /* Set flash endianness */
266     base->MCR &= ~QuadSPI_MCR_END_CFG_MASK;
267     base->MCR |= QuadSPI_MCR_END_CFG(config->endian);
268 
269     /* Enable QSPI again */
270     QSPI_Enable(base, true);
271 }
272 
273 #if (!defined(FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG)) || !FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG
274 /*!
275  * @brief Configures the serial flash DQS parameter.
276  *
277  * This function configures the serial flash DQS relevant parameters, such as the delay chain tap number, .
278  * DQS shift phase, whether need to inverse and the rxc sample clock selection.
279  *
280  * @param base Pointer to QuadSPI Type.
281  * @param config Dqs configuration parameters.
282  */
QSPI_SetDqsConfig(QuadSPI_Type * base,qspi_dqs_config_t * config)283 void QSPI_SetDqsConfig(QuadSPI_Type *base, qspi_dqs_config_t *config)
284 {
285     uint32_t soccrVal;
286     uint32_t mcrVal;
287 
288     /* Disable module */
289     QSPI_Enable(base, false);
290 
291     mcrVal = base->MCR;
292 
293     mcrVal &= ~(QuadSPI_MCR_DQS_EN_MASK | QuadSPI_MCR_DQS_LAT_EN_MASK);
294     /* Enable DQS. */
295     mcrVal |= QuadSPI_MCR_DQS_EN_MASK;
296 
297     /* Configure DQS phase, inverse and loopback atrribute */
298     soccrVal = base->SOCCR;
299     soccrVal &=
300         ~(QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK | QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK |
301           QuadSPI_SOCCR_DQS_PHASE_SEL_MASK | QuadSPI_SOCCR_DQS_INV_EN_MASK | QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL_MASK
302 #if defined(QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL_MASK)
303           | QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL_MASK
304 #endif
305         );
306     soccrVal |= QuadSPI_SOCCR_DQS_PHASE_SEL(config->shift);
307 
308     switch (config->rxSampleClock)
309     {
310         case kQSPI_ReadSampleClkInternalLoopback:
311             soccrVal |= QuadSPI_SOCCR_DQS_LOOPBACK_EN_MASK;
312             break;
313         case kQSPI_ReadSampleClkExternalInputFromDqsPad:
314             mcrVal |= QuadSPI_MCR_DQS_LAT_EN_MASK;
315             break;
316         case kQSPI_ReadSampleClkLoopbackFromDqsPad:
317             soccrVal |= QuadSPI_SOCCR_DQS_LOOPBACK_FROM_PAD_MASK;
318             break;
319         default:
320             assert(false);
321             break;
322     }
323 
324     soccrVal |= (QuadSPI_SOCCR_DQS_INV_EN(config->enableDQSClkInverse) |
325                  QuadSPI_SOCCR_DQS_IFA_DELAY_CHAIN_SEL(config->portADelayTapNum)
326 #if defined(QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL_MASK)
327                  | QuadSPI_SOCCR_DQS_IFB_DELAY_CHAIN_SEL(config->portBDelayTapNum)
328 #endif
329     );
330 
331     base->MCR   = mcrVal;
332     base->SOCCR = soccrVal;
333 
334     /* Enable QSPI again */
335     QSPI_Enable(base, true);
336 }
337 #endif /* FSL_FEATURE_QSPI_HAS_NO_SOCCR_REG */
338 
339 /*!
340  * brief Software reset for the QSPI logic.
341  *
342  * This function sets the software reset flags for both AHB and buffer domain and
343  * resets both AHB buffer and also IP FIFOs.
344  *
345  * param base Pointer to QuadSPI Type.
346  */
QSPI_SoftwareReset(QuadSPI_Type * base)347 void QSPI_SoftwareReset(QuadSPI_Type *base)
348 {
349     uint32_t i = 0;
350 
351     /* Reset AHB domain and buffer domian */
352     base->MCR |= (QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK);
353 
354     /* Wait several time for the reset to finish, this method came from IC team */
355     for (i = 0; i < 100U; i++)
356     {
357         __NOP();
358     }
359 
360     /* Disable QSPI module */
361     QSPI_Enable(base, false);
362 
363     /* Clear the reset flags */
364     base->MCR &= ~(QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK);
365 
366     /* Enable QSPI module */
367     QSPI_Enable(base, true);
368 }
369 
370 /*!
371  * brief Gets the Rx data register address used for DMA operation.
372  *
373  * This function returns the Rx data register address or Rx buffer address
374  * according to the Rx read area settings.
375  *
376  * param base Pointer to QuadSPI Type.
377  * return QSPI Rx data register address.
378  */
QSPI_GetRxDataRegisterAddress(QuadSPI_Type * base)379 uint32_t QSPI_GetRxDataRegisterAddress(QuadSPI_Type *base)
380 {
381     /* From RDBR */
382     if (0U != (base->RBCT & QuadSPI_RBCT_RXBRD_MASK))
383     {
384         return (uint32_t)(&(base->RBDR[0]));
385     }
386     else
387     {
388         /* From ARDB */
389         return FSL_FEATURE_QSPI_ARDB_BASE;
390     }
391 }
392 
393 /*! brief Executes IP commands located in LUT table.
394  *
395  * param base Pointer to QuadSPI Type.
396  * param index IP command located in which LUT table index.
397  */
QSPI_ExecuteIPCommand(QuadSPI_Type * base,uint32_t index)398 void QSPI_ExecuteIPCommand(QuadSPI_Type *base, uint32_t index)
399 {
400     while (0U != (QSPI_GetStatusFlags(base) & ((uint32_t)kQSPI_Busy | (uint32_t)kQSPI_IPAccess)))
401     {
402     }
403     QSPI_ClearCommandSequence(base, kQSPI_IPSeq);
404 
405     /* Write the seqid bit */
406     base->IPCR = ((base->IPCR & (~QuadSPI_IPCR_SEQID_MASK)) | QuadSPI_IPCR_SEQID(index / 4U));
407 }
408 
409 /*! brief Executes AHB commands located in LUT table.
410  *
411  * param base Pointer to QuadSPI Type.
412  * param index AHB command located in which LUT table index.
413  */
QSPI_ExecuteAHBCommand(QuadSPI_Type * base,uint32_t index)414 void QSPI_ExecuteAHBCommand(QuadSPI_Type *base, uint32_t index)
415 {
416     while (0U != (QSPI_GetStatusFlags(base) & ((uint32_t)kQSPI_Busy | (uint32_t)kQSPI_AHBAccess)))
417     {
418     }
419     QSPI_ClearCommandSequence(base, kQSPI_BufferSeq);
420     base->BFGENCR = ((base->BFGENCR & (~QuadSPI_BFGENCR_SEQID_MASK)) | QuadSPI_BFGENCR_SEQID(index / 4U));
421 }
422 
423 /*! brief Updates the LUT table.
424  *
425  * param base Pointer to QuadSPI Type.
426  * param index Which LUT index needs to be located. It should be an integer divided by 4.
427  * param cmd Command sequence array.
428  */
QSPI_UpdateLUT(QuadSPI_Type * base,uint32_t index,uint32_t * cmd)429 void QSPI_UpdateLUT(QuadSPI_Type *base, uint32_t index, uint32_t *cmd)
430 {
431     uint8_t i = 0;
432 
433     /* Unlock the LUT */
434     base->LUTKEY = 0x5AF05AF0U;
435     base->LCKCR  = 0x2U;
436 
437     /* Write data into LUT */
438     for (i = 0; i < 4U; i++)
439     {
440         base->LUT[index + i] = *cmd;
441         cmd++;
442     }
443 
444     /* Lcok LUT again */
445     base->LUTKEY = 0x5AF05AF0U;
446     base->LCKCR  = 0x1U;
447 }
448 
449 #if defined(FSL_FEATURE_QSPI_SOCCR_HAS_CLR_LPCAC) && (FSL_FEATURE_QSPI_SOCCR_HAS_CLR_LPCAC)
450 
451 /*! brief Clears the QSPI cache.
452  *
453  * param base Pointer to QuadSPI Type.
454  */
QSPI_ClearCache(QuadSPI_Type * base)455 void QSPI_ClearCache(QuadSPI_Type *base)
456 {
457     uint32_t soccrVal;
458 
459     soccrVal = base->SOCCR;
460     /* Write 1 to clear cache. */
461     base->SOCCR = (soccrVal | QuadSPI_SOCCR_CLR_LPCAC_MASK);
462 
463     /* Write 0 to after cache is cleared. */
464     base->SOCCR = (soccrVal & (~QuadSPI_SOCCR_CLR_LPCAC_MASK));
465 }
466 #endif
467 
468 /*! brief Set the RX buffer readout area.
469  *
470  * This function can set the RX buffer readout, from AHB bus or IP Bus.
471  * param base QSPI base address.
472  * param area QSPI Rx buffer readout area. AHB bus buffer or IP bus buffer.
473  */
QSPI_SetReadDataArea(QuadSPI_Type * base,qspi_read_area_t area)474 void QSPI_SetReadDataArea(QuadSPI_Type *base, qspi_read_area_t area)
475 {
476     base->RBCT &= ~QuadSPI_RBCT_RXBRD_MASK;
477     base->RBCT |= QuadSPI_RBCT_RXBRD(area);
478 }
479 
480 /*!
481  * brief Receives data from data FIFO.
482  *
483  * param base QSPI base pointer
484  * return The data in the FIFO.
485  */
QSPI_ReadData(QuadSPI_Type * base)486 uint32_t QSPI_ReadData(QuadSPI_Type *base)
487 {
488     if (0U != (base->RBCT & QuadSPI_RBCT_RXBRD_MASK))
489     {
490         return base->RBDR[0];
491     }
492     else
493     {
494         /* Data from ARDB. */
495         return *((uint32_t *)FSL_FEATURE_QSPI_ARDB_BASE);
496     }
497 }
498 
499 /*!
500  * brief Sends a buffer of data bytes using a  blocking method.
501  * note This function blocks via polling until all bytes have been sent.
502  * param base QSPI base pointer
503  * param buffer The data bytes to send
504  * param size The number of data bytes to send
505  */
QSPI_WriteBlocking(QuadSPI_Type * base,uint32_t * buffer,size_t size)506 void QSPI_WriteBlocking(QuadSPI_Type *base, uint32_t *buffer, size_t size)
507 {
508     assert(size >= 16U);
509 
510     uint32_t i = 0;
511 
512     for (i = 0; i < size / 4U; i++)
513     {
514         /* Check if the buffer is full */
515         while (0U != (QSPI_GetStatusFlags(base) & (uint32_t)kQSPI_TxBufferFull))
516         {
517         }
518         base->TBDR = *buffer++;
519     }
520 }
521 
522 /*!
523  * brief Receives a buffer of data bytes using a blocking method.
524  * note This function blocks via polling until all bytes have been sent. Users shall notice that
525  * this receive size shall not bigger than 64 bytes. As this interface is used to read flash status registers.
526  * For flash contents read, please use AHB bus read, this is much more efficiency.
527  *
528  * param base QSPI base pointer
529  * param buffer The data bytes to send
530  * param size The number of data bytes to receive
531  */
QSPI_ReadBlocking(QuadSPI_Type * base,uint32_t * buffer,size_t size)532 void QSPI_ReadBlocking(QuadSPI_Type *base, uint32_t *buffer, size_t size)
533 {
534     uint32_t i     = 0;
535     uint32_t j     = 0;
536     uint32_t temp  = 0;
537     uint32_t level = (base->RBCT & QuadSPI_RBCT_WMRK_MASK) + 1U;
538 
539     while (i < size / 4U)
540     {
541         /* Check if there is data */
542         if ((size / 4U - i) < level)
543         {
544             do
545             {
546                 temp = (base->RBSR & QuadSPI_RBSR_RDBFL_MASK) >> QuadSPI_RBSR_RDBFL_SHIFT;
547             } while (0U == temp);
548         }
549         else
550         {
551             while ((QSPI_GetStatusFlags(base) & (uint32_t)kQSPI_RxWatermark) == 0U)
552             {
553             }
554         }
555 
556         level = (level < (size / 4U - i)) ? level : (size / 4U - i);
557 
558         /* Data from RBDR */
559         if (0U != (base->RBCT & QuadSPI_RBCT_RXBRD_MASK))
560         {
561             for (j = 0; j < level; j++)
562             {
563                 buffer[i + j] = base->RBDR[j];
564             }
565         }
566         else
567         {
568             /* Data from ARDB. */
569             for (j = 0; j < level; j++)
570             {
571                 buffer[i + j] = ((uint32_t *)FSL_FEATURE_QSPI_ARDB_BASE)[j];
572             }
573         }
574         i += level;
575 
576         /* Clear the Buffer */
577         QSPI_ClearErrorFlag(base, (uint32_t)kQSPI_RxBufferDrain);
578     }
579 }
580