1 /*
2  * Copyright 2021-2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8 *   @file Qspi_Ip.c
9 *
10 *   @addtogroup IPV_QSPI
11 *   @{
12 */
13 
14 
15 #ifdef __cplusplus
16 extern "C"{
17 #endif
18 
19 #include "Mcal.h"
20 #include "OsIf.h"
21 #include "Qspi_Ip_Controller.h"
22 #include "Qspi_Ip_Common.h"
23 #include "Qspi_Ip.h"
24 #include "Qspi_Ip_Hyperflash.h"
25 
26 
27 /*==================================================================================================
28 *                              SOURCE FILE VERSION INFORMATION
29 ==================================================================================================*/
30 #define QSPI_IP_VENDOR_ID_C                    43
31 #define QSPI_IP_AR_RELEASE_MAJOR_VERSION_C     4
32 #define QSPI_IP_AR_RELEASE_MINOR_VERSION_C     7
33 #define QSPI_IP_AR_RELEASE_REVISION_VERSION_C  0
34 #define QSPI_IP_SW_MAJOR_VERSION_C             2
35 #define QSPI_IP_SW_MINOR_VERSION_C             0
36 #define QSPI_IP_SW_PATCH_VERSION_C             0
37 /*==================================================================================================
38 *                                     FILE VERSION CHECKS
39 ==================================================================================================*/
40 #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
41     /* Check if current file and Mcal.h header file are of the same Autosar version */
42     #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != MCAL_AR_RELEASE_MAJOR_VERSION) || \
43          (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != MCAL_AR_RELEASE_MINOR_VERSION) \
44         )
45         #error "AutoSar Version Numbers of Qspi_Ip.c and Mcal.h are different"
46     #endif
47 
48     /* Check if current file and OsIf.h header file are of the same Autosar version */
49     #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != OSIF_AR_RELEASE_MAJOR_VERSION) || \
50          (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != OSIF_AR_RELEASE_MINOR_VERSION) \
51         )
52         #error "AutoSar Version Numbers of Qspi_Ip.c and OsIf.h are different"
53     #endif
54 #endif
55 
56 /* Check if current file and Qspi_Ip_Controller header file are of the same vendor */
57 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_CONTROLLER_VENDOR_ID_H)
58     #error "Qspi_Ip.c and Qspi_Ip_Controller.h have different vendor ids"
59 #endif
60 /* Check if current file and Qspi_Ip_Controller header file are of the same Autosar version */
61 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C    != QSPI_IP_CONTROLLER_AR_RELEASE_MAJOR_VERSION_H) || \
62      (QSPI_IP_AR_RELEASE_MINOR_VERSION_C    != QSPI_IP_CONTROLLER_AR_RELEASE_MINOR_VERSION_H) || \
63      (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_CONTROLLER_AR_RELEASE_REVISION_VERSION_H) \
64     )
65     #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip_Controller.h are different"
66 #endif
67 /* Check if current file and Qspi_Ip_Controller header file are of the same Software version */
68 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_CONTROLLER_SW_MAJOR_VERSION_H) || \
69      (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_CONTROLLER_SW_MINOR_VERSION_H) || \
70      (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_CONTROLLER_SW_PATCH_VERSION_H) \
71     )
72     #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip_Controller.h are different"
73 #endif
74 
75 /* Check if current file and Qspi_Ip_Common header file are of the same vendor */
76 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_COMMON_VENDOR_ID_H)
77     #error "Qspi_Ip.c and Qspi_Ip_Common.h have different vendor ids"
78 #endif
79 /* Check if current file and Qspi_Ip_Common header file are of the same Autosar version */
80 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C    != QSPI_IP_COMMON_AR_RELEASE_MAJOR_VERSION_H) || \
81      (QSPI_IP_AR_RELEASE_MINOR_VERSION_C    != QSPI_IP_COMMON_AR_RELEASE_MINOR_VERSION_H) || \
82      (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_COMMON_AR_RELEASE_REVISION_VERSION_H) \
83     )
84     #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip_Common.h are different"
85 #endif
86 /* Check if current file and Qspi_Ip_Common header file are of the same Software version */
87 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_COMMON_SW_MAJOR_VERSION_H) || \
88      (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_COMMON_SW_MINOR_VERSION_H) || \
89      (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_COMMON_SW_PATCH_VERSION_H) \
90     )
91     #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip_Common.h are different"
92 #endif
93 
94 /* Check if current file and Qspi_Ip header file are of the same vendor */
95 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_VENDOR_ID_H)
96     #error "Qspi_Ip.c and Qspi_Ip.h have different vendor ids"
97 #endif
98 /* Check if current file and Qspi_Ip header file are of the same Autosar version */
99 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C    != QSPI_IP_AR_RELEASE_MAJOR_VERSION_H) || \
100      (QSPI_IP_AR_RELEASE_MINOR_VERSION_C    != QSPI_IP_AR_RELEASE_MINOR_VERSION_H) || \
101      (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_AR_RELEASE_REVISION_VERSION_H) \
102     )
103     #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip.h are different"
104 #endif
105 /* Check if current file and Qspi_Ip header file are of the same Software version */
106 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_SW_MAJOR_VERSION_H) || \
107      (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_SW_MINOR_VERSION_H) || \
108      (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_SW_PATCH_VERSION_H) \
109     )
110     #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip.h are different"
111 #endif
112 
113 /* Check if current file and Qspi_Ip_Hyperflash header file are of the same vendor */
114 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_HYPERFLASH_VENDOR_ID_H)
115     #error "Qspi_Ip.c and Qspi_Ip_Hyperflash.h have different vendor ids"
116 #endif
117 /* Check if current file and Qspi_Ip_Hyperflash header file are of the same Autosar version */
118 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C    != QSPI_IP_HYPERFLASH_AR_RELEASE_MAJOR_VERSION_H) || \
119      (QSPI_IP_AR_RELEASE_MINOR_VERSION_C    != QSPI_IP_HYPERFLASH_AR_RELEASE_MINOR_VERSION_H) || \
120      (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_HYPERFLASH_AR_RELEASE_REVISION_VERSION_H) \
121     )
122     #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip_Hyperflash.h are different"
123 #endif
124 /* Check if current file and Qspi_Ip_Hyperflash header file are of the same Software version */
125 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_HYPERFLASH_SW_MAJOR_VERSION_H) || \
126      (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_HYPERFLASH_SW_MINOR_VERSION_H) || \
127      (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_HYPERFLASH_SW_PATCH_VERSION_H) \
128     )
129     #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip_Hyperflash.h are different"
130 #endif
131 
132 
133 /*******************************************************************************
134  * Variables
135  ******************************************************************************/
136 #if (QSPI_IP_MEM_INSTANCE_COUNT > 0)
137 
138 /*When multicore type3 is enabled on MemAcc, global variables must be allocated to share memory section */
139 #if( QSPI_IP_MULTICORE_ENABLED == STD_ON)
140 #define MEM_43_EXFLS_START_SEC_VAR_SHARED_CLEARED_UNSPECIFIED_NO_CACHEABLE
141 #else
142 #define MEM_43_EXFLS_START_SEC_VAR_CLEARED_UNSPECIFIED
143 #endif
144 #include "Mem_43_EXFLS_MemMap.h"
145 
146 /* Pointer to runtime state structures */
147 VAR_SEC_NOCACHE(Qspi_Ip_MemoryStateStructure) Qspi_Ip_StateType Qspi_Ip_MemoryStateStructure[QSPI_IP_MEM_INSTANCE_COUNT];
148 
149 #if( QSPI_IP_MULTICORE_ENABLED == STD_ON)
150 #define MEM_43_EXFLS_STOP_SEC_VAR_SHARED_CLEARED_UNSPECIFIED_NO_CACHEABLE
151 #else
152 #define MEM_43_EXFLS_STOP_SEC_VAR_CLEARED_UNSPECIFIED
153 #endif
154 #include "Mem_43_EXFLS_MemMap.h"
155 
156 /*******************************************************************************
157  * Macros
158  ******************************************************************************/
159 
160 
161 /*******************************************************************************
162  * Private Functions
163  ******************************************************************************/
164 
165 #define MEM_43_EXFLS_START_SEC_CODE
166 #include "Mem_43_EXFLS_MemMap.h"
167 
168 static Qspi_Ip_StatusType Qspi_Ip_WriteEnable(uint32 instance);
169 
170 static Qspi_Ip_StatusType Qspi_Ip_InitReset(uint32 instance,
171                                             uint16 resetCmdLut,
172                                             uint8 resetCmdCount,
173                                             const Qspi_Ip_StateType *state
174                                            );
175 
176 static Qspi_Ip_StatusType Qspi_Ip_InitWriteReg(uint32 instance,
177                                                const Qspi_Ip_InitOperationType *operation
178                                               );
179 
180 static Qspi_Ip_StatusType Qspi_Ip_InitRMWReg(uint32 instance,
181                                              const Qspi_Ip_InitOperationType *operation
182                                             );
183 
184 static Qspi_Ip_StatusType Qspi_Ip_InitReadReg(uint32 instance,
185                                               const Qspi_Ip_InitOperationType *operation
186                                              );
187 
188 static Qspi_Ip_StatusType Qspi_Ip_InitProtection(uint32 instance,
189                                                  const Qspi_Ip_StateType *state
190                                                 );
191 
192 static Qspi_Ip_StatusType Qspi_Ip_InitOperation(uint32 instance,
193                                                 const Qspi_Ip_StateType *state,
194                                                 uint8 initOp
195                                                );
196 
197 static inline uint32 Qspi_Ip_CalcPaddingRead(const Qspi_Ip_StateType *state,
198                                              uint32 *address,
199                                              uint32 *size
200                                             );
201 
202 static uint16 Qspi_Ip_InitLutSeq(uint32 instance,
203                                  uint16 VirtualLut,
204                                  uint8 LutRegister
205                                 );
206 
207 static void Qspi_Ip_DeinitLutSeq(uint32 instance,
208                                    uint8 LutRegister
209                                   );
210 
211 /*FUNCTION**********************************************************************
212  *
213  * Function Name : Qspi_Ip_InitLutSeq
214  * Description   : Initializes one sequence in the LUT table from a virtual table sequence. Returns start index of next sequence.
215 */
Qspi_Ip_InitLutSeq(uint32 instance,uint16 VirtualLut,uint8 LutRegister)216 static uint16 Qspi_Ip_InitLutSeq(uint32 instance,
217                                  uint16 VirtualLut,
218                                  uint8 LutRegister
219                                 )
220 {
221     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
222     const Qspi_Ip_InstrOpType *virtualLutTable = state->configuration->lutSequences.lutOps;
223     Qspi_Ip_InstrOpType operation1, operation2;
224     uint16 vLutIdx = VirtualLut;         /* Index in virtual LUT  */
225     uint8  pLutIdx = 0U;                 /* Index in physical LUT */
226     uint32 lutData[FEATURE_QSPI_LUT_SEQUENCE_SIZE];  /* Data to be written to the physical LUTs */
227 
228     do
229     {
230 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
231         DEV_ASSERT_QSPI(vLutIdx < state->configuration->lutSequences.opCount);
232 #endif
233         operation1 = virtualLutTable[vLutIdx];
234         vLutIdx++;
235         operation2 = QSPI_IP_LUT_SEQ_END;
236         if (operation1 != QSPI_IP_LUT_SEQ_END)
237         {
238 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
239             DEV_ASSERT_QSPI(vLutIdx < state->configuration->lutSequences.opCount);
240 #endif
241             operation2 = virtualLutTable[vLutIdx];
242             vLutIdx++;
243         }
244         /* Add two operations to lut sequence */
245 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
246         DEV_ASSERT_QSPI(pLutIdx < FEATURE_QSPI_LUT_SEQUENCE_SIZE);
247 #endif
248         lutData[pLutIdx] = QSPI_IP_PACK_LUT_REG(operation1, operation2);
249         pLutIdx++;
250     }
251     while (operation2 != QSPI_IP_LUT_SEQ_END);
252 
253 #if (FEATURE_QSPI_HAS_SFP == 1)
254     /* Clear the rest of sequence to avoid the effect of the previous command.
255        This prevent the SFP block from identifying the wrong type of transaction.
256     */
257     for (; pLutIdx < FEATURE_QSPI_LUT_SEQUENCE_SIZE; pLutIdx++)
258     {
259         lutData[pLutIdx] = QSPI_IP_PACK_LUT_REG(QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END);
260     }
261 #endif
262 
263     /* Write data to physical LUT registers */
264     Qspi_Ip_WriteLuts(state->connection->qspiInstance, FEATURE_QSPI_LUT_SEQUENCE_SIZE * LutRegister, lutData, pLutIdx);
265 
266     return vLutIdx;
267 }
268 
269 
270 /*FUNCTION**********************************************************************
271  *
272  * Function Name : Qspi_Ip_DeinitLutSeq
273  * Description   : DeInitializes one sequence in the LUT table from a virtual table sequence.
274 */
Qspi_Ip_DeinitLutSeq(uint32 instance,uint8 LutRegister)275 static void Qspi_Ip_DeinitLutSeq(uint32 instance,
276                                  uint8 LutRegister
277                                 )
278 {
279     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
280     const uint32 lutData[FEATURE_QSPI_LUT_SEQUENCE_SIZE] = {0U};  /* Data to be written to the physical LUTs */
281 
282     /* Write data to physical LUT registers */
283     Qspi_Ip_WriteLuts(state->connection->qspiInstance, FEATURE_QSPI_LUT_SEQUENCE_SIZE * LutRegister, lutData, FEATURE_QSPI_LUT_SEQUENCE_SIZE);
284 }
285 
286 
287 /*FUNCTION**********************************************************************
288  *
289  * Function Name : Qspi_Ip_SetValue
290  * Description   : Converts a long value in data to be sent to flash
291  */
Qspi_Ip_SetValue(uint8 * data,uint8 size,uint32 value)292 static inline void Qspi_Ip_SetValue(uint8 *data,
293                                     uint8 size,
294                                     uint32 value
295                                    )
296 {
297     uint8 cnt;
298     uint32 temp = value;
299 
300     /* Put value in the data buffer */
301     for (cnt = 0U; cnt < size; cnt++)
302     {
303         data[cnt] = (uint8)(temp & 0xFFU);
304         temp >>= 8U;
305     }
306 }
307 
308 /*FUNCTION**********************************************************************
309  *
310  * Function Name : Qspi_Ip_SetBitfield
311  * Description   : Sets a new value in a register bitfield
312  */
Qspi_Ip_SetBitfield(uint8 * data,uint8 size,uint8 shift,uint8 width,uint32 value)313 static void Qspi_Ip_SetBitfield(uint8 *data,
314                                 uint8 size,
315                                 uint8 shift,
316                                 uint8 width,
317                                 uint32 value
318                                )
319 {
320     uint8 cnt;
321     uint32 longData = 0UL;
322     uint32 mask;
323 
324     /* Pack data in a long value (data[0] is LSB, data[size-1] is MSB) */
325     for (cnt = 0U; cnt < size; cnt++)
326     {
327         longData = (longData << 8U) + data[size - 1U - cnt];
328     }
329     /* Apply change */
330     mask = ((1UL << (uint32)width) - 1UL) << (uint32)shift;
331     longData &= ~mask;
332     longData |= (value << shift) & mask;
333     /* Put data back in the data buffer (data[0] is LSB, data[size-1] is MSB) */
334     for (cnt = 0U; cnt < size; cnt++)
335     {
336         data[cnt] = (uint8)(longData & 0xFFU);
337         longData >>= 8U;
338     }
339 }
340 
341 
342 /*FUNCTION**********************************************************************
343  *
344  * Function Name : Qspi_Ip_GetBitfield
345  * Description   : Extracts the value of a register bitfield
346  */
Qspi_Ip_GetBitfield(const uint8 * data,uint8 size,uint8 shift,uint8 width)347 static uint32 Qspi_Ip_GetBitfield(const uint8 *data,
348                                   uint8 size,
349                                   uint8 shift,
350                                   uint8 width
351                                  )
352 {
353     uint8 cnt;
354     uint32 longData = 0U;
355     uint32 mask;
356     uint32 value;
357 
358     /* Pack data in a long value (data[0] is LSB, data[size-1] is MSB) */
359     for (cnt = 0U; cnt < size; cnt++)
360     {
361         longData = (longData << 8U) + data[size - 1U - cnt];
362     }
363     /* Extract field */
364     mask = (1UL << (uint32)width) - 1UL;
365     value = (longData >> shift) & mask;
366     return value;
367 }
368 
369 
370 /*FUNCTION**********************************************************************
371  *
372  * Function Name : Qspi_Ip_UpdateStatusReg
373  * Description   : Updates a bitfield in the status register
374 * @implements      Qspi_Ip_UpdateStatusReg_Activity */
Qspi_Ip_UpdateStatusReg(uint32 instance,uint8 offset,uint8 width,uint8 value)375 static Qspi_Ip_StatusType Qspi_Ip_UpdateStatusReg(uint32 instance,
376                                                   uint8 offset,
377                                                   uint8 width,
378                                                   uint8 value
379                                                  )
380 {
381     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
382     const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
383     uint8 data[4U];
384     Qspi_Ip_StatusType status;
385 
386     /* Read status register */
387     status = Qspi_Ip_RunReadCommand(instance, statusConfig->statusRegReadLut, 0U, data, NULL_PTR, statusConfig->regSize);
388 
389     if (STATUS_QSPI_IP_SUCCESS == status)
390     {
391         /* Check existing value, write status register only if needed */
392         if (value != Qspi_Ip_GetBitfield(data, statusConfig->regSize, offset, width))
393         {
394             Qspi_Ip_SetBitfield(data, statusConfig->regSize, offset, width, value);
395         }
396         /* send WREN command for status register */
397         if (statusConfig->writeEnableSRLut != QSPI_IP_LUT_INVALID)
398         {
399             status = Qspi_Ip_RunCommand(instance, statusConfig->writeEnableSRLut, 0U);
400         }
401         if (STATUS_QSPI_IP_SUCCESS == status)
402         {
403             /* send write status register command */
404             status = Qspi_Ip_RunWriteCommand(instance, statusConfig->statusRegWriteLut, 0U, data, statusConfig->regSize);
405         }
406     }
407 
408     return status;
409 }
410 
411 /*FUNCTION**********************************************************************
412  *
413  * Function Name : Qspi_Ip_CheckStatusReg
414  * Description   : Checks a bitfield in the status register
415 * @implements      Qspi_Ip_CheckStatusReg_Activity */
Qspi_Ip_CheckStatusReg(uint32 instance,uint8 offset,uint8 width,uint8 * value)416 static Qspi_Ip_StatusType Qspi_Ip_CheckStatusReg(uint32 instance,
417                                                  uint8 offset,
418                                                  uint8 width,
419                                                  uint8 *value
420                                                 )
421 {
422     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
423     const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
424     uint8 data[4];
425     Qspi_Ip_StatusType status;
426 
427     /* Read status register */
428     status = Qspi_Ip_RunReadCommand(instance, statusConfig->statusRegReadLut, 0U, data, NULL_PTR, statusConfig->regSize);
429     if (STATUS_QSPI_IP_SUCCESS == status)
430     {
431         /* Extract bit-field */
432         *value = (uint8)Qspi_Ip_GetBitfield(data, statusConfig->regSize, offset, width);
433     }
434 
435     return status;
436 }
437 
438 
439 /*FUNCTION**********************************************************************
440  *
441  * Function Name : Qspi_Ip_WriteEnable
442  * Description   : Enables the serial flash memory for a program or erase operation
443 * @implements      Qspi_Ip_WriteEnable_Activity */
Qspi_Ip_WriteEnable(uint32 instance)444 static Qspi_Ip_StatusType Qspi_Ip_WriteEnable(uint32 instance)
445 {
446     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
447     const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
448 
449     uint32 retries = QSPI_IP_MAX_RETRY + 1U;
450     Qspi_Ip_StatusType status = STATUS_QSPI_IP_TIMEOUT;
451     Qspi_Ip_StatusType cmdStatus;
452     uint8 welValue = 0U;
453 
454     MCAL_FAULT_INJECTION_POINT(FLS_FIP_FR_ERROR_IPCOMMAND_WAIT_IN_WREN);
455 
456     while (retries > 0UL)
457     {
458         /* send WREN command */
459         cmdStatus = Qspi_Ip_RunCommand(instance, statusConfig->writeEnableLut, 0U);
460         if (cmdStatus != STATUS_QSPI_IP_SUCCESS)
461         {
462             status = cmdStatus;
463         }
464         /* check WEL bit */
465         cmdStatus = Qspi_Ip_CheckStatusReg(instance, statusConfig->writeEnableOffset, 1U, &welValue);
466         if (STATUS_QSPI_IP_SUCCESS == cmdStatus)
467         {
468             /* 1 == check WEL */
469             if (1U == welValue)
470             {
471                 status = STATUS_QSPI_IP_SUCCESS;
472                 break;
473             }
474         }
475         else
476         {
477             /* record error */
478             status = cmdStatus;
479         }
480         retries--;
481     }
482 
483     return status;
484 }
485 
486 
487 /*FUNCTION**********************************************************************
488  *
489  * Function Name : Qspi_Ip_SerialflashSectorErase
490  * Description   : Erase a sector in the serial flash.
491  */
Qspi_Ip_SerialflashSectorErase(uint32 instance,uint32 address,uint16 eraseLut)492 static Qspi_Ip_StatusType Qspi_Ip_SerialflashSectorErase(uint32 instance,
493                                                          uint32 address,
494                                                          uint16 eraseLut
495                                                         )
496 {
497     Qspi_Ip_StatusType status;
498 
499     /* enable write before erasing */
500     status = Qspi_Ip_WriteEnable(instance);
501 
502     MCAL_FAULT_INJECTION_POINT(FLS_FIP_FR_ERROR_IPCOMMAND_WAIT_IN_BASICERS);
503 
504     if (STATUS_QSPI_IP_SUCCESS == status)
505     {
506         /* launch erase command and return */
507         status = Qspi_Ip_RunCommand(instance, eraseLut, address);
508     }
509 
510     return status;
511 }
512 
513 
514 /*FUNCTION**********************************************************************
515  *
516  * Function Name : Qspi_Ip_BasicErase
517  * Description   : Perform one of the supported erase types in the serial flash.
518  * @implements      Qspi_Ip_BasicErase_Activity */
Qspi_Ip_BasicErase(uint32 instance,uint32 address,uint16 eraseLut)519 static Qspi_Ip_StatusType Qspi_Ip_BasicErase(uint32 instance,
520                                              uint32 address,
521                                              uint16 eraseLut
522                                             )
523 {
524     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
525     Qspi_Ip_StatusType status;
526 
527     /* Check device type */
528     switch (state->configuration->memType)
529     {
530         case QSPI_IP_HYPER_FLASH:
531             status = Qspi_Ip_HyperflashSectorErase(instance, address);
532             break;
533 
534         case QSPI_IP_SERIAL_FLASH:
535             status = Qspi_Ip_SerialflashSectorErase(instance, address, eraseLut);
536             break;
537         default:
538             status = STATUS_QSPI_IP_ERROR; /* unknown operation */
539             break;
540     }
541 
542     return status;
543 }
544 
545 
546 /*FUNCTION**********************************************************************
547  *
548  * Function Name : Qspi_Ip_CheckMemoryStatus
549  * Description   : Check that the memory is idle. Used internally by the driver during initialization
550  */
Qspi_Ip_CheckMemoryStatus(uint32 instance,uint16 virtualLut)551 static Qspi_Ip_StatusType Qspi_Ip_CheckMemoryStatus(uint32 instance,
552                                                     uint16 virtualLut
553                                                    )
554 {
555     Qspi_Ip_StatusType status;
556     uint8 busyValue;
557     uint8 data[4];
558     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
559     const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
560 
561     /* Check if the QuadSPI controller is idle */
562     status = Qspi_Ip_ControllerGetStatus(state->connection->qspiInstance);
563     if (STATUS_QSPI_IP_SUCCESS == status)
564     {
565         /* Check if the operation has finished in the serial flash */
566         /* Read status register */
567         status = Qspi_Ip_RunReadCommand(instance, virtualLut, 0U, data, NULL_PTR, statusConfig->regSize);
568         if (STATUS_QSPI_IP_SUCCESS == status)
569         {
570             /* Extract bit-field */
571             busyValue = (uint8)Qspi_Ip_GetBitfield(data, statusConfig->regSize, statusConfig->busyOffset, 1U);
572             if (busyValue == statusConfig->busyValue)
573             {
574                 /* Flash device is busy */
575                 status = STATUS_QSPI_IP_BUSY;
576             }
577             MCAL_FAULT_INJECTION_POINT(FLS_FIP_SR_BUSY_CHECKCOMMANDCOMPLETE);
578         }
579     }
580 
581     return status;
582 }
583 
584 
585 /*FUNCTION**********************************************************************
586  *
587  * Function Name : Qspi_Ip_WaitCommandComplete
588  * Description   : Wait until external memory is not busy
589  */
Qspi_Ip_WaitCommandComplete(uint32 instance,uint16 VirtualLut)590 static Qspi_Ip_StatusType Qspi_Ip_WaitCommandComplete(uint32 instance,
591                                                        uint16 VirtualLut
592                                                       )
593 {
594     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
595     uint32  ElapsedTicks = 0UL;
596     uint32  TimeoutTicks;
597     uint32  CurrentTicks;
598 
599     /* Prepare timeout counter */
600     TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_FLS_INIT_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
601     CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
602     /* Wait for the command to complete */
603     do
604     {
605         /* Get memory status */
606         status = Qspi_Ip_CheckMemoryStatus(instance, VirtualLut);
607         ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
608         /* Check timeout */
609         if (ElapsedTicks >= TimeoutTicks)
610         {
611             status = STATUS_QSPI_IP_TIMEOUT;
612             break;
613         }
614     }
615     while (STATUS_QSPI_IP_BUSY == status);
616 
617     return status;
618 }
619 
620 
621 /*FUNCTION**********************************************************************
622  *
623  * Function Name : Qspi_Ip_WaitResetComplete
624  * Description   : Wait until external memory is available for operation after a reset
625 * @implements      Qspi_Ip_CheckResetComplete_Activity */
Qspi_Ip_WaitResetComplete(void)626 static void Qspi_Ip_WaitResetComplete(void)
627 {
628     uint32 ElapsedTicks = 0UL;
629     uint32 TimeoutTicks;
630     uint32 CurrentTicks;
631 
632     /* Prepare timeout counter */
633     TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_RESET_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
634     CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
635     /* Wait for the specified time */
636     do
637     {
638         ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
639     }
640     while (ElapsedTicks < TimeoutTicks);
641 }
642 
643 
644 /*FUNCTION**********************************************************************
645  *
646  * Function Name : Qspi_Ip_InitWriteReg
647  * Description   : Write the configured value into a register of external flash device
648 * @implements      Qspi_Ip_InitWriteReg_Activity */
Qspi_Ip_InitWriteReg(uint32 instance,const Qspi_Ip_InitOperationType * operation)649 static Qspi_Ip_StatusType Qspi_Ip_InitWriteReg(uint32 instance,
650                                                const Qspi_Ip_InitOperationType * operation
651                                               )
652 {
653     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
654     uint8 value[4U];
655 
656     /* write a value in a register */
657     if (QSPI_IP_LUT_INVALID != operation->weLut)
658     {
659         /* send WREN command */
660         status = Qspi_Ip_RunCommand(instance, operation->weLut, operation->addr);
661     }
662     if (STATUS_QSPI_IP_SUCCESS == status)
663     {
664         Qspi_Ip_SetValue(value, operation->size, operation->value);
665         status = Qspi_Ip_RunWriteCommand(instance, operation->command1Lut, operation->addr, value, operation->size);
666     }
667 
668     return status;
669 }
670 
671 
672 /*FUNCTION**********************************************************************
673  *
674  * Function Name : Qspi_Ip_InitRMWReg
675  * Description   : Change a bitfield in a register of external flash device
676 * @implements      Qspi_Ip_InitRMWReg_Activity */
Qspi_Ip_InitRMWReg(uint32 instance,const Qspi_Ip_InitOperationType * operation)677 static Qspi_Ip_StatusType Qspi_Ip_InitRMWReg(uint32 instance,
678                                              const Qspi_Ip_InitOperationType *operation
679                                             )
680 {
681     Qspi_Ip_StatusType status;
682     uint32 fieldVal;
683     uint8 value[4U];
684 
685     /* Read current register value */
686     status = Qspi_Ip_RunReadCommand(instance, operation->command1Lut, operation->addr, value, NULL_PTR, operation->size);
687     if (STATUS_QSPI_IP_SUCCESS == status)
688     {
689         /* Retrieve target bitfield */
690         fieldVal = Qspi_Ip_GetBitfield(value, operation->size, operation->shift, operation->width);
691         if (fieldVal != operation->value)
692         {
693             /* Modify target bitfield */
694             Qspi_Ip_SetBitfield(value, operation->size, operation->shift, operation->width, operation->value);
695             if (QSPI_IP_LUT_INVALID != operation->weLut)
696             {
697                 /* Send WREN command */
698                 status = Qspi_Ip_RunCommand(instance, operation->weLut, operation->addr);
699             }
700             if (STATUS_QSPI_IP_SUCCESS == status)
701             {
702                 /* Write back register value; use second LUT command */
703                 status = Qspi_Ip_RunWriteCommand(instance, operation->command2Lut, operation->addr, (uint8 *)&value, operation->size);
704             }
705         }
706     }
707 
708     return status;
709 }
710 
711 
712 /*FUNCTION**********************************************************************
713  *
714  * Function Name : Qspi_Ip_InitReadReg
715  * Description   : Read the register's value of external flash device and loop until matching the configured one
716 * @implements      Qspi_Ip_InitReadReg_Activity */
Qspi_Ip_InitReadReg(uint32 instance,const Qspi_Ip_InitOperationType * operation)717 static Qspi_Ip_StatusType Qspi_Ip_InitReadReg(uint32 instance,
718                                               const Qspi_Ip_InitOperationType *operation
719                                              )
720 {
721     Qspi_Ip_StatusType status;
722     uint32 fieldVal = 0xFFFFFFFFUL;  /* Invalid initial value */
723     uint8 value[4U];
724     uint32 ElapsedTicks = 0UL;
725     uint32 TimeoutTicks;
726     uint32 CurrentTicks;
727 
728     /* Prepare timeout counter */
729     TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_FLS_INIT_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
730     CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
731     do
732     {
733         /* read current register value */
734         status = Qspi_Ip_RunReadCommand(instance, operation->command1Lut, operation->addr, value, NULL_PTR, operation->size);
735         if (STATUS_QSPI_IP_SUCCESS == status)
736         {
737             /* retrieve target bitfield */
738             fieldVal = Qspi_Ip_GetBitfield(value, operation->size, operation->shift, operation->width);
739         }
740         ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
741         if (ElapsedTicks >= TimeoutTicks)
742         {
743             status = STATUS_QSPI_IP_TIMEOUT;
744             break;
745         }
746     }
747     while (fieldVal != operation->value);
748 
749     return status;
750 }
751 
752 /*FUNCTION**********************************************************************
753  *
754  * Function Name : Qspi_Ip_InitOperation
755  * Description   : Execute initialization sequence to get the serial flash memory in the target state for operation */
Qspi_Ip_InitOperation(uint32 instance,const Qspi_Ip_StateType * state,uint8 initOp)756 static Qspi_Ip_StatusType Qspi_Ip_InitOperation(uint32 instance,
757                                                 const Qspi_Ip_StateType *state,
758                                                 uint8 initOp
759                                                )
760 {
761     const Qspi_Ip_InitOperationType *initOperations = state->configuration->initConfiguration.operations;
762     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
763 
764     switch (initOperations[initOp].opType)
765     {
766         case QSPI_IP_OP_TYPE_CMD:
767             /* Execute a simple command */
768             status = Qspi_Ip_RunCommand(instance, initOperations[initOp].command1Lut, initOperations[initOp].addr);
769             break;
770 
771         case QSPI_IP_OP_TYPE_WRITE_REG:
772             /* Write value into the register */
773             status = Qspi_Ip_InitWriteReg(instance, &initOperations[initOp]);
774             break;
775 
776         case QSPI_IP_OP_TYPE_RMW_REG:
777             /* Change a bitfield in the register */
778             status = Qspi_Ip_InitRMWReg(instance, &initOperations[initOp]);
779             break;
780 
781         case QSPI_IP_OP_TYPE_READ_REG:
782             /* Check a bitfield in the register */
783             status = Qspi_Ip_InitReadReg(instance, &initOperations[initOp]);
784             break;
785 
786         case QSPI_IP_OP_TYPE_QSPI_CFG:
787             /* Re-initialize QSPI controller with the given configuration */
788             (void)Qspi_Ip_ControllerDeinit(state->connection->qspiInstance);
789             status = Qspi_Ip_ControllerInit(state->connection->qspiInstance, initOperations[initOp].ctrlCfgPtr);
790             break;
791 
792         default:
793             status = STATUS_QSPI_IP_ERROR; /* unknown operation */
794             break;
795     }   /* switch */
796 
797     return status;
798 
799 }
800 
801 /*FUNCTION**********************************************************************
802  *
803  * Function Name : Qspi_Ip_InitDevice
804  * Description   : Execute initialization sequence to get the serial flash memory in the target state for operation
805 * @implements      Qspi_Ip_InitDevice_Activity */
Qspi_Ip_InitDevice(uint32 instance,const Qspi_Ip_StateType * state)806 static Qspi_Ip_StatusType Qspi_Ip_InitDevice(uint32 instance,
807                                              const Qspi_Ip_StateType *state
808                                             )
809 {
810     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
811     uint8 initConfigOpCount = state->configuration->initConfiguration.opCount;
812     uint8 initOp;
813 
814     MCAL_FAULT_INJECTION_POINT(FLS_FIP_FR_ERROR_IPCOMMAND_INITDEVICE);
815 
816     /* Perform operations in initialization list (common) */
817     for (initOp = 0; initOp < initConfigOpCount; initOp++)
818     {
819         status = Qspi_Ip_InitOperation(instance, state, initOp);
820 
821         if (STATUS_QSPI_IP_SUCCESS != status)
822         {
823             break;
824         }
825     }
826 
827     /* Perform device initialization (specific) */
828     if (STATUS_QSPI_IP_SUCCESS == status)
829     {
830 
831     if (QSPI_IP_HYPER_FLASH == state->configuration->memType)
832     {
833         status = Qspi_Ip_HyperflashInit(instance);
834     }
835     }
836     else
837     {
838        status =  STATUS_QSPI_IP_ERROR;
839     }
840 
841     return status;
842 }
843 
844 
845 /*FUNCTION**********************************************************************
846  *
847  * Function Name : Qspi_Ip_InitProtection
848  * Description   : Update the protection configuration value if needed
849 * @implements      Qspi_Ip_InitProtection_Activity */
Qspi_Ip_InitProtection(uint32 instance,const Qspi_Ip_StateType * state)850 static Qspi_Ip_StatusType Qspi_Ip_InitProtection(uint32 instance,
851                                                  const Qspi_Ip_StateType *state
852                                                 )
853 {
854     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
855     uint8 configProtection = state->configuration->statusConfig.blockProtectionValue;
856     uint8 getProtection = 0U;
857 
858     if (state->configuration->statusConfig.blockProtectionWidth != 0U)
859     {
860         /* Ensure the previous command is completed */
861         status = Qspi_Ip_WaitCommandComplete(instance, state->configuration->statusConfig.statusRegReadLut);
862         if (STATUS_QSPI_IP_SUCCESS == status)
863         {
864             /* Read and check the current setting */
865             status = Qspi_Ip_GetProtection(instance, &getProtection);
866             if ((STATUS_QSPI_IP_SUCCESS == status) && (getProtection != configProtection))
867             {
868                 /* Set new setting */
869                 status = Qspi_Ip_SetProtection(instance, configProtection);
870                 if (STATUS_QSPI_IP_SUCCESS == status)
871                 {
872                     /* Ensure the write is completed  */
873                     status = Qspi_Ip_WaitCommandComplete(instance, state->configuration->statusConfig.statusRegReadLut);
874                 }
875             }
876         }
877     }
878 
879     return status;
880 }
881 
882 
883 /*FUNCTION**********************************************************************
884  *
885  * Function Name : Qspi_Ip_InitReset
886  * Description   : Perform the software reset sequence
887 * @implements      Qspi_Ip_InitReset_Activity */
Qspi_Ip_InitReset(uint32 instance,uint16 resetCmdLut,uint8 resetCmdCount,const Qspi_Ip_StateType * state)888 static Qspi_Ip_StatusType Qspi_Ip_InitReset(uint32 instance,
889                                             uint16 resetCmdLut,
890                                             uint8 resetCmdCount,
891                                             const Qspi_Ip_StateType *state
892                                            )
893 {
894     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
895     uint16 virtualLut = resetCmdLut;
896     uint8 cnt;
897 
898     if (QSPI_IP_LUT_INVALID != resetCmdLut)
899     {
900         for (cnt = 0U; cnt < resetCmdCount; cnt++)
901         {
902             /* Copy sequence in LUT registers */
903             virtualLut = Qspi_Ip_InitLutSeq(instance, virtualLut, QSPI_IP_COMMAND_LUT);
904 
905             /* Run QSPI command */
906             status = Qspi_Ip_IpCommand(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress);
907             if (status != STATUS_QSPI_IP_SUCCESS)
908             {
909                 break;
910             }
911 
912             /* Clear sequence in LUT registers */
913             Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
914         }
915         if (STATUS_QSPI_IP_SUCCESS == status)
916         {
917             /* Ensure flash is ready after reset */
918             Qspi_Ip_WaitResetComplete();
919         }
920     }
921 
922     return status;
923 }
924 
925 
926 /*FUNCTION**********************************************************************
927  *
928  * Function Name : Qspi_Ip_SerialflashEraseChip
929  * Description   : Erase the entire serial flash
930  */
Qspi_Ip_SerialflashEraseChip(uint32 instance)931 static Qspi_Ip_StatusType Qspi_Ip_SerialflashEraseChip(uint32 instance)
932 {
933     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
934     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
935 
936     if (state->configuration->eraseSettings.chipEraseLut != QSPI_IP_LUT_INVALID)
937     {
938         /* enable write before erasing */
939         status = Qspi_Ip_WriteEnable(instance);
940         if (STATUS_QSPI_IP_SUCCESS == status)
941         {
942             /* launch erase command */
943             status = Qspi_Ip_RunCommand(instance, state->configuration->eraseSettings.chipEraseLut, 0U);
944         }
945     }
946 
947     return status;
948 }
949 
950 
951 /*FUNCTION**********************************************************************
952  *
953  * Function Name : Qspi_Ip_SerialflashGetMemoryStatus
954  * Description   : Get the status of the last operation
955  */
Qspi_Ip_SerialflashGetMemoryStatus(uint32 instance)956 static Qspi_Ip_StatusType Qspi_Ip_SerialflashGetMemoryStatus(uint32 instance)
957 {
958     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
959     const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
960     uint8 busyValue = 0xFFU;  /* Invalid initial value */
961     Qspi_Ip_StatusType status;
962 
963     /* Get the value of busy bit */
964     status = Qspi_Ip_CheckStatusReg(instance, statusConfig->busyOffset, 1U, &busyValue);
965     /* Check BUSY value */
966     if (busyValue == statusConfig->busyValue)
967     {
968         /* Write/erase in progress */
969         status = STATUS_QSPI_IP_BUSY;
970     }
971 
972     return status;
973 }
974 
975 
976 /*FUNCTION**********************************************************************
977  *
978  * Function Name : Qspi_Ip_PatchReadCommand
979  * Description   : Patch the command sequence before using
980  */
Qspi_Ip_PatchReadCommand(uint32 instance,uint16 readLut)981 static void Qspi_Ip_PatchReadCommand(uint32 instance,
982                                      uint16 readLut
983                                     )
984 {
985     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
986 
987     /* Check device type */
988     switch (state->configuration->memType)
989     {
990         case QSPI_IP_HYPER_FLASH:
991             Qspi_Ip_HyperflashPatchReadCommand(instance, readLut);
992             break;
993 
994         case QSPI_IP_SERIAL_FLASH:
995             /* Nothing to do with Serial flash */
996             (void)readLut;
997             break;
998 
999         default:
1000             (void)readLut; /* unknown operation */
1001             break;
1002     }
1003 }
1004 
1005 
1006 /*******************************************************************************
1007  * Code
1008  ******************************************************************************/
1009 
1010 /*FUNCTION**********************************************************************
1011  *
1012  * Function Name : Qspi_Ip_RunCommand
1013  * Description   : Launches a simple command for the serial flash
1014 * @implements      Qspi_Ip_RunCommand_Activity */
Qspi_Ip_RunCommand(uint32 instance,uint16 lut,uint32 addr)1015 Qspi_Ip_StatusType Qspi_Ip_RunCommand(uint32 instance,
1016                                       uint16 lut,
1017                                       uint32 addr
1018                                      )
1019 {
1020     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1021     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1022 
1023 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1024     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1025     DEV_ASSERT_QSPI(lut != QSPI_IP_LUT_INVALID);
1026     DEV_ASSERT_QSPI(addr < state->configuration->memSize);
1027 #endif
1028 
1029     if (lut != QSPI_IP_LUT_INVALID)
1030     {
1031         /* Copy sequence in LUT registers */
1032         (void)Qspi_Ip_InitLutSeq(instance, lut, QSPI_IP_COMMAND_LUT);
1033 
1034         /* Run QSPI command */
1035         status = Qspi_Ip_IpCommand(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress + addr);
1036 
1037         /* Clear sequence in LUT registers */
1038         Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
1039     }
1040 
1041     return status;
1042 }
1043 
1044 
1045 /*FUNCTION**********************************************************************
1046  *
1047  * Function Name : Qspi_Ip_RunReadCommand
1048  * Description   : Launches a read command for the serial flash
1049 * @implements      Qspi_Ip_RunReadCommand_Activity */
Qspi_Ip_RunReadCommand(uint32 instance,uint16 lut,uint32 addr,uint8 * dataRead,const uint8 * dataCmp,uint32 size)1050 Qspi_Ip_StatusType Qspi_Ip_RunReadCommand(uint32 instance,
1051                                           uint16 lut,
1052                                           uint32 addr,
1053                                           uint8 * dataRead,
1054                                           const uint8 * dataCmp,
1055                                           uint32 size
1056                                          )
1057 {
1058     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1059     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1060 
1061 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1062     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1063     DEV_ASSERT_QSPI(lut != QSPI_IP_LUT_INVALID);
1064     DEV_ASSERT_QSPI(addr < state->configuration->memSize);
1065     DEV_ASSERT_QSPI((size > 0UL) && ((addr + size) <= state->configuration->memSize));
1066 #endif
1067 
1068     if (lut != QSPI_IP_LUT_INVALID)
1069     {
1070         /* Copy sequence in LUT registers */
1071         (void)Qspi_Ip_InitLutSeq(instance, lut, QSPI_IP_COMMAND_LUT);
1072 
1073         /* Run QSPI command */
1074         status = Qspi_Ip_IpRead(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress + addr, dataRead, dataCmp, size);
1075 
1076         /* Clear sequence in LUT registers */
1077         Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
1078     }
1079 
1080     return status;
1081 }
1082 
1083 
1084 /*FUNCTION**********************************************************************
1085  *
1086  * Function Name : Qspi_Ip_RunWriteCommand
1087  * Description   : Launches a write command for the serial flash
1088  * @implements     Qspi_Ip_RunWriteCommand_Activity */
Qspi_Ip_RunWriteCommand(uint32 instance,uint16 lut,uint32 addr,const uint8 * data,uint32 size)1089 Qspi_Ip_StatusType Qspi_Ip_RunWriteCommand(uint32 instance,
1090                                            uint16 lut,
1091                                            uint32 addr,
1092                                            const uint8 * data,
1093                                            uint32 size
1094                                           )
1095 {
1096     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1097     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1098 
1099 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1100     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1101     DEV_ASSERT_QSPI(lut != QSPI_IP_LUT_INVALID);
1102     DEV_ASSERT_QSPI(addr < state->configuration->memSize);
1103     DEV_ASSERT_QSPI((size > 0UL) && ((addr + size) <= state->configuration->memSize));
1104     DEV_ASSERT_QSPI(data != NULL_PTR);
1105 #endif
1106 
1107     if (lut != QSPI_IP_LUT_INVALID)
1108     {
1109         /* Copy sequence in LUT registers */
1110         (void)Qspi_Ip_InitLutSeq(instance, lut, QSPI_IP_COMMAND_LUT);
1111 
1112         /* Run QSPI command */
1113         status = Qspi_Ip_IpWrite(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress + addr, data, size);
1114 
1115         /* Clear sequence in LUT registers */
1116         Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
1117     }
1118 
1119     return status;
1120 }
1121 
1122 
1123 
1124 /*FUNCTION**********************************************************************
1125  *
1126  * Function Name : Qspi_Ip_EraseBlock
1127  * Description   : Erase a sector in the serial flash.
1128  *                 The size must match one of the device's erase types.
1129  * @implements     Qspi_Ip_EraseBlock_Activity */
Qspi_Ip_EraseBlock(uint32 instance,uint32 address,uint32 size)1130 Qspi_Ip_StatusType Qspi_Ip_EraseBlock(uint32 instance,
1131                                       uint32 address,
1132                                       uint32 size
1133                                      )
1134 {
1135     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1136     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1137     uint8 eraseType;
1138 
1139 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1140     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1141     DEV_ASSERT_QSPI(address < state->configuration->memSize);
1142     DEV_ASSERT_QSPI((size > 0UL) && ((address + size) <= state->configuration->memSize));
1143 #endif
1144 
1145     /* Check address range */
1146     if (address < state->configuration->memSize)
1147     {
1148         /* find the suited erase type */
1149         for (eraseType = 0U; eraseType < QSPI_IP_ERASE_TYPES; eraseType++)
1150         {
1151             if ((state->configuration->eraseSettings.eraseTypes[eraseType].eraseLut != QSPI_IP_LUT_INVALID) &&
1152                 (size == (uint32)((uint32)1U << (state->configuration->eraseSettings.eraseTypes[eraseType].size))))
1153             {
1154                 break;
1155             }
1156         }
1157         /* if erase type was found, launch the erase */
1158         if (eraseType < QSPI_IP_ERASE_TYPES)
1159         {
1160             status = Qspi_Ip_BasicErase(instance, address, state->configuration->eraseSettings.eraseTypes[eraseType].eraseLut);
1161             if (STATUS_QSPI_IP_SUCCESS == status)
1162             {
1163                 state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE;
1164             }
1165         }
1166     }
1167 
1168     return status;
1169 }
1170 
1171 
1172 /*FUNCTION**********************************************************************
1173  *
1174  * Function Name : Qspi_Ip_EraseChip
1175  * Description   : Erase the entire serial flash
1176  * @implements     Qspi_Ip_EraseChip_Activity */
Qspi_Ip_EraseChip(uint32 instance)1177 Qspi_Ip_StatusType Qspi_Ip_EraseChip(uint32 instance)
1178 {
1179 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1180     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1181 #endif
1182 
1183     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1184     Qspi_Ip_StatusType status;
1185 
1186     /* Check device type */
1187     switch (state->configuration->memType)
1188     {
1189         case QSPI_IP_HYPER_FLASH:
1190             status = Qspi_Ip_HyperflashChipErase(instance);
1191             break;
1192 
1193         case QSPI_IP_SERIAL_FLASH:
1194             status = Qspi_Ip_SerialflashEraseChip(instance);
1195             break;
1196 
1197         default:
1198             status = STATUS_QSPI_IP_ERROR; /* unknown operation */
1199             break;
1200     }
1201 
1202     if (STATUS_QSPI_IP_SUCCESS == status)
1203     {
1204         state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE;
1205     }
1206 
1207     return status;
1208 }
1209 
1210 
1211 /*FUNCTION**********************************************************************
1212  *
1213  * Function Name : Qspi_Ip_ProgramSuspend
1214  * Description   : Suspends a program operation
1215  * @implements     Qspi_Ip_ProgramSuspend_Activity */
Qspi_Ip_ProgramSuspend(uint32 instance)1216 Qspi_Ip_StatusType Qspi_Ip_ProgramSuspend(uint32 instance)
1217 {
1218 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1219     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1220 #endif
1221 
1222     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1223     Qspi_Ip_StatusType status;
1224 
1225     /* Issue the Program Suspend command */
1226     status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.programSuspendLut, 0U);
1227     state->lastCommand = QSPI_IP_LAST_COMMAND_WRITE_SUSPEND;
1228 
1229     return status;
1230 }
1231 
1232 
1233 /*FUNCTION**********************************************************************
1234  *
1235  * Function Name : Qspi_Ip_ProgramResume
1236  * Description   : Resumes a program operation
1237  * @implements     Qspi_Ip_ProgramResume_Activity */
Qspi_Ip_ProgramResume(uint32 instance)1238 Qspi_Ip_StatusType Qspi_Ip_ProgramResume(uint32 instance)
1239 {
1240 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1241     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1242 #endif
1243 
1244     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1245     Qspi_Ip_StatusType status;
1246 
1247     /* Issue the Program Resume command */
1248     status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.programResumeLut, 0U);
1249     state->lastCommand = QSPI_IP_LAST_COMMAND_WRITE;
1250 
1251     return status;
1252 }
1253 
1254 
1255 /*FUNCTION**********************************************************************
1256  *
1257  * Function Name : Qspi_Ip_EraseSuspend
1258  * Description   : Suspends an erase operation
1259  * @implements     Qspi_Ip_EraseSuspend_Activity */
Qspi_Ip_EraseSuspend(uint32 instance)1260 Qspi_Ip_StatusType Qspi_Ip_EraseSuspend(uint32 instance)
1261 {
1262 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1263     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1264 #endif
1265 
1266     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1267     Qspi_Ip_StatusType status;
1268 
1269     /* Issue the Erase Suspend command */
1270     status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.eraseSuspendLut, 0U);
1271     state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE_SUSPEND;
1272 
1273     return status;
1274 }
1275 
1276 
1277 /*FUNCTION**********************************************************************
1278  *
1279  * Function Name : Qspi_Ip_EraseResume
1280  * Description   : Resumes an erase operation
1281  * @implements     Qspi_Ip_EraseResume_Activity */
Qspi_Ip_EraseResume(uint32 instance)1282 Qspi_Ip_StatusType Qspi_Ip_EraseResume(uint32 instance)
1283 {
1284 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1285     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1286 #endif
1287 
1288     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1289     Qspi_Ip_StatusType status;
1290 
1291     /* Issue the Erase Resume command */
1292     status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.eraseResumeLut, 0U);
1293     state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE;
1294 
1295     return status;
1296 }
1297 
1298 
1299 /*FUNCTION**********************************************************************
1300  *
1301  * Function Name : Qspi_Ip_Reset
1302  * Description   : Issues a software reset command
1303  * @implements     Qspi_Ip_Reset_Activity */
Qspi_Ip_Reset(uint32 instance)1304 Qspi_Ip_StatusType Qspi_Ip_Reset(uint32 instance)
1305 {
1306 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1307     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1308 #endif
1309 
1310     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1311     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1312     uint16 resetCmdLut;        /*!< First command in reset sequence            */
1313     uint8 resetCmdCount;       /*!< Number of commands in reset sequence       */
1314 
1315     resetCmdLut = state->configuration->resetSettings.resetCmdLut;
1316     if (QSPI_IP_LUT_INVALID != resetCmdLut)
1317     {
1318         resetCmdCount = state->configuration->resetSettings.resetCmdCount;
1319         /* Perform reset */
1320         status = Qspi_Ip_InitReset(instance, resetCmdLut, resetCmdCount, state);
1321         /* Bring corresponding controller to initial configuration if required */
1322         if ((STATUS_QSPI_IP_SUCCESS == status) && (state->configuration->ctrlAutoCfgPtr != NULL_PTR))
1323         {
1324             status = Qspi_Ip_ControllerInit(state->connection->qspiInstance, state->configuration->ctrlAutoCfgPtr);
1325         }
1326         if (STATUS_QSPI_IP_SUCCESS == status)
1327         {
1328             /* Execute initial setup of external device */
1329             status = Qspi_Ip_InitDevice(instance, state);
1330         }
1331     }
1332 
1333     /* If enabled, call the reset callout. */
1334     if (NULL_PTR != state->configuration->resetCallout)
1335     {
1336         status = state->configuration->resetCallout(instance);
1337     }
1338 
1339     return status;
1340 }
1341 
1342 
1343 /*FUNCTION**********************************************************************
1344  *
1345  * Function Name : Qspi_Ip_GetMemoryStatus
1346  * Description   : Get the status of the last operation
1347  * @implements     Qspi_Ip_GetMemoryStatus_Activity */
Qspi_Ip_GetMemoryStatus(uint32 instance)1348 Qspi_Ip_StatusType Qspi_Ip_GetMemoryStatus(uint32 instance)
1349 {
1350 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1351     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1352 #endif
1353 
1354     Qspi_Ip_StatusType status;
1355     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1356 
1357     /* Check if the QuadSPI command is complete */
1358     status = Qspi_Ip_ControllerGetStatus(state->connection->qspiInstance);
1359 
1360     if (STATUS_QSPI_IP_SUCCESS == status)
1361     {
1362         /* Check device type */
1363         switch (state->configuration->memType)
1364         {
1365             case QSPI_IP_HYPER_FLASH:
1366                 /* Check if the operation has finished in the hyper flash */
1367                 status = Qspi_Ip_HyperflashGetMemoryStatus(instance);
1368                 break;
1369 
1370             case QSPI_IP_SERIAL_FLASH:
1371                 /* Check if the operation has finished in the serial flash */
1372                 status = Qspi_Ip_SerialflashGetMemoryStatus(instance);
1373                 break;
1374             default:
1375                 status = STATUS_QSPI_IP_ERROR; /* unknown operation */
1376                 break;
1377         }
1378     }
1379 
1380     if (STATUS_QSPI_IP_SUCCESS == status)
1381     {
1382         /* Call user callout, if available, to check operation result */
1383         if ((state->lastCommand != QSPI_IP_LAST_COMMAND_NONE) && (NULL_PTR != state->configuration->errorCheckCallout))
1384         {
1385             status = state->configuration->errorCheckCallout(instance);
1386         }
1387         state->lastCommand = QSPI_IP_LAST_COMMAND_NONE;
1388     }
1389 
1390     return status;
1391 }
1392 
1393 
1394 /*FUNCTION**********************************************************************
1395  *
1396  * Function Name : Qspi_Ip_CalcPaddingRead
1397  * Description   : Calculates the number of padding bytes to handle reading from unaligned addresses
1398  */
Qspi_Ip_CalcPaddingRead(const Qspi_Ip_StateType * state,uint32 * address,uint32 * size)1399 static inline uint32 Qspi_Ip_CalcPaddingRead(const Qspi_Ip_StateType *state,
1400                                              uint32 *address,
1401                                              uint32 *size
1402                                             )
1403 {
1404     const uint32 qspiInstance  = state->connection->qspiInstance;
1405     const uint32 readAlignment = state->connection->memAlignment;
1406 
1407     /* Checking for unaligned addresses */
1408     uint32 offset = *address & (readAlignment - 1U);
1409     if (offset != 0U)
1410     {
1411         /* The number of padding bytes to handle unaligned address */
1412         Qspi_Ip_MemoryPadding[qspiInstance] = (uint8)offset;
1413         /* Decreasing the address */
1414         *address -= offset;
1415         /* Increasing the size to compensate */
1416         *size += offset;
1417     }
1418 
1419     return offset;
1420 }
1421 
1422 
1423 /*FUNCTION**********************************************************************
1424  *
1425  * Function Name : Qspi_Ip_Read
1426  * Description   : Read data from serial flash
1427  * @implements     Qspi_Ip_Read_Activity */
Qspi_Ip_Read(uint32 instance,uint32 address,uint8 * data,uint32 size)1428 Qspi_Ip_StatusType Qspi_Ip_Read(uint32 instance,
1429                                 uint32 address,
1430                                 uint8 * data,
1431                                 uint32 size
1432                                )
1433 {
1434     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1435     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1436     uint32 crtAddress = address;
1437     uint8 * crtData = data;
1438     uint32 crtSize = size;
1439     uint32 chunkSize = QSPI_IP_MAX_READ_SIZE;
1440     uint32 offset;
1441     uint32 ElapsedTicks = 0UL;
1442     uint32 TimeoutTicks;
1443     uint32 CurrentTicks;
1444 
1445 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1446     DEV_ASSERT_QSPI(crtAddress < state->configuration->memSize);
1447     DEV_ASSERT_QSPI((crtSize > 0UL) && ((crtAddress + crtSize) <= state->configuration->memSize));
1448     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1449     DEV_ASSERT_QSPI(data != NULL_PTR);
1450 #endif
1451 
1452     /* Checks and handles unaligned addresses */
1453     offset = Qspi_Ip_CalcPaddingRead(state, &crtAddress, &crtSize);
1454 
1455     /* Prepare timeout counter */
1456     TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_READ_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
1457     CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
1458     while ((crtSize > 0UL) && (STATUS_QSPI_IP_SUCCESS == status))
1459     {
1460         if (chunkSize > crtSize)
1461         {
1462             /* Adjust size for last chunk */
1463             chunkSize = crtSize;
1464         }
1465         /* Check timeout */
1466         ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
1467         if (ElapsedTicks >= TimeoutTicks)
1468         {
1469             status = STATUS_QSPI_IP_TIMEOUT;
1470             break;
1471         }
1472 
1473         /* Patch the command sequence before using */
1474         Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1475         status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, crtAddress, crtData, NULL_PTR, chunkSize);
1476         /* Move to next chunk */
1477         crtSize    -= chunkSize;
1478         crtAddress += chunkSize;
1479         crtData     = &(crtData[chunkSize - offset]);  /* Handle alignment for the first read */
1480         offset      = 0U;
1481 
1482         /* Call user callout, if available, to check ECC or CRC status */
1483         if ((STATUS_QSPI_IP_SUCCESS == status) && (NULL_PTR != state->configuration->eccCheckCallout))
1484         {
1485             status = state->configuration->eccCheckCallout(instance, crtAddress, chunkSize);
1486         }
1487     }
1488     return status;
1489 }
1490 
1491 
1492 /*FUNCTION**********************************************************************
1493  *
1494  * Function Name : Qspi_Ip_ReadId
1495  * Description   : Read manufacturer ID from serial flash
1496  * @implements     Qspi_Ip_ReadId_Activity */
Qspi_Ip_ReadId(uint32 instance,uint8 * data)1497 Qspi_Ip_StatusType Qspi_Ip_ReadId(uint32 instance,
1498                                   uint8 * data
1499                                  )
1500 {
1501 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1502     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1503     DEV_ASSERT_QSPI(data != NULL_PTR);
1504 #endif
1505 
1506     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1507     Qspi_Ip_StatusType status;
1508 
1509     /* Check device type */
1510     switch (state->configuration->memType)
1511     {
1512         case QSPI_IP_HYPER_FLASH:
1513             status = Qspi_Ip_HyperflashReadId(instance,
1514                                               state->configuration->hfConfig->deviceIdWordAddress,
1515                                               data,
1516                                               state->configuration->readIdSettings.readIdSize);
1517             break;
1518 
1519         case QSPI_IP_SERIAL_FLASH:
1520             status = Qspi_Ip_RunReadCommand(instance,
1521                                             state->configuration->readIdSettings.readIdLut,
1522                                             0U,
1523                                             data,
1524                                             NULL_PTR,
1525                                             state->configuration->readIdSettings.readIdSize);
1526             break;
1527         default:
1528             status = STATUS_QSPI_IP_ERROR; /* unknown operation */
1529             break;
1530     }
1531 
1532     return status;
1533 }
1534 
1535 
1536 /*FUNCTION**********************************************************************
1537  *
1538  * Function Name : Qspi_Ip_ProgramVerify
1539  * Description   : Verifies data written in serial flash
1540  * @implements     Qspi_Ip_ProgramVerify_Activity */
Qspi_Ip_ProgramVerify(uint32 instance,uint32 address,const uint8 * data,uint32 size)1541 Qspi_Ip_StatusType Qspi_Ip_ProgramVerify(uint32 instance,
1542                                          uint32 address,
1543                                          const uint8 * data,
1544                                          uint32 size
1545                                         )
1546 {
1547     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1548     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1549     uint32 crtAddress = address;
1550     const uint8 * crtData = data;
1551     uint32 crtSize = size;
1552     uint32 chunkSize = QSPI_IP_MAX_READ_SIZE;
1553     uint32 offset;
1554     uint32 ElapsedTicks = 0UL;
1555     uint32 TimeoutTicks;
1556     uint32 CurrentTicks;
1557 
1558 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1559     DEV_ASSERT_QSPI(crtAddress < state->configuration->memSize);
1560     DEV_ASSERT_QSPI((crtSize > 0UL) && ((crtAddress + crtSize) <= state->configuration->memSize));
1561     DEV_ASSERT_QSPI(data != NULL_PTR);
1562     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1563 #endif
1564 
1565     /* Checks and handles unaligned addresses */
1566     offset = Qspi_Ip_CalcPaddingRead(state, &crtAddress, &crtSize);
1567 
1568     /* Prepare timeout counter */
1569     TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_READ_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
1570     CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
1571     while ((crtSize > 0U) && (STATUS_QSPI_IP_SUCCESS == status))
1572     {
1573         if (chunkSize > crtSize)
1574         {
1575             /* Adjust size for last chunk */
1576             chunkSize = crtSize;
1577         }
1578         /* Check timeout */
1579         ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
1580         if (ElapsedTicks >= TimeoutTicks)
1581         {
1582             status = STATUS_QSPI_IP_TIMEOUT;
1583             break;
1584         }
1585 
1586         /* Patch the command sequence before using */
1587         Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1588         status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, crtAddress, NULL_PTR, crtData, chunkSize);
1589         /* Move to next chunk */
1590         crtSize    -= chunkSize;
1591         crtAddress += chunkSize;
1592         crtData     = &(crtData[chunkSize - offset]);  /* Handle alignment for the first read */
1593         offset      = 0U;
1594     }
1595     return status;
1596 }
1597 
1598 
1599 
1600 /*FUNCTION**********************************************************************
1601  *
1602  * Function Name : Qspi_Ip_EraseVerify
1603  * Description   : Verifies that an area in serial flash is in erased state
1604  * @implements     Qspi_Ip_EraseVerify_Activity */
Qspi_Ip_EraseVerify(uint32 instance,uint32 address,uint32 size)1605 Qspi_Ip_StatusType Qspi_Ip_EraseVerify(uint32 instance,
1606                                        uint32 address,
1607                                        uint32 size
1608                                       )
1609 {
1610     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1611     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1612     uint32 crtAddress = address;
1613     uint32 crtSize = size;
1614     uint32 chunkSize = QSPI_IP_MAX_READ_SIZE;
1615     uint32  ElapsedTicks = 0UL;
1616     uint32  TimeoutTicks;
1617     uint32  CurrentTicks;
1618 
1619 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1620     DEV_ASSERT_QSPI(crtAddress < state->configuration->memSize);
1621     DEV_ASSERT_QSPI((crtSize > 0UL) && ((crtAddress + crtSize) <= state->configuration->memSize));
1622     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1623 #endif
1624 
1625     /* Checks and handles unaligned addresses */
1626     (void)Qspi_Ip_CalcPaddingRead(state, &crtAddress, &crtSize);
1627 
1628     /* Prepare timeout counter */
1629     TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_READ_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
1630     CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
1631     while ((crtSize > 0UL) && (STATUS_QSPI_IP_SUCCESS == status))
1632     {
1633         if (chunkSize > crtSize)
1634         {
1635             /* Adjust size for last chunk */
1636             chunkSize = crtSize;
1637         }
1638         /* Check timeout */
1639         ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
1640         if (ElapsedTicks >= TimeoutTicks)
1641         {
1642             status = STATUS_QSPI_IP_TIMEOUT;
1643             break;
1644         }
1645 
1646         /* Patch the command sequence before issuing */
1647         Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1648         status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, crtAddress, NULL_PTR, NULL_PTR, chunkSize);
1649         /* Move to next chunk */
1650         crtSize    -= chunkSize;
1651         crtAddress += chunkSize;
1652     }
1653     return status;
1654 }
1655 
1656 
1657 /*FUNCTION**********************************************************************
1658  *
1659  * Function Name : Qspi_Ip_CalcPaddingWrite
1660  * Description   : Calculates the number of padding bytes to handle writing to unaligned addresses
1661  */
Qspi_Ip_CalcPaddingWrite(const Qspi_Ip_StateType * state,uint32 address,uint32 size)1662 static inline uint32 Qspi_Ip_CalcPaddingWrite(const Qspi_Ip_StateType *state,
1663                                               uint32 address,
1664                                               uint32 size
1665                                              )
1666 {
1667     uint32 qspiInstance  = state->connection->qspiInstance;
1668     uint32 alignmentMask = (uint32)(state->connection->memAlignment) - 1UL;
1669 
1670     /* The number of pre-padding bytes */
1671     uint32 prePadding    = address & alignmentMask;
1672 
1673     /* The number of post-padding bytes */
1674     uint32 endAddr       = address + size - 1UL;
1675     uint32 postPadding   = alignmentMask - (endAddr & alignmentMask);
1676 
1677     /* Store padding information */
1678     Qspi_Ip_MemoryPadding[qspiInstance] = (uint8)((prePadding << 4UL) | postPadding);
1679 
1680     /* Decreasing the address */
1681     return (address - prePadding);
1682 }
1683 
1684 
1685 /*FUNCTION**********************************************************************
1686  *
1687  * Function Name : Qspi_Ip_Program
1688  * Description   : Writes data in serial flash
1689  * @implements     Qspi_Ip_Program_Activity */
Qspi_Ip_Program(uint32 instance,uint32 address,const uint8 * data,uint32 size)1690 Qspi_Ip_StatusType Qspi_Ip_Program(uint32 instance,
1691                                    uint32 address,
1692                                    const uint8 * data,
1693                                    uint32 size
1694                                   )
1695 {
1696     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1697     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1698     uint32 alignedAddress;
1699 
1700 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1701     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1702     DEV_ASSERT_QSPI(address < state->configuration->memSize);
1703     DEV_ASSERT_QSPI(data != NULL_PTR);
1704     DEV_ASSERT_QSPI((size > 0UL) && ((address + size) <= state->configuration->memSize));
1705 #endif
1706 
1707     /* Check address range and page size */
1708     if ((address < state->configuration->memSize) && ((size <= state->configuration->pageSize)))
1709     {
1710         /* Write data to the flash device */
1711         switch (state->configuration->memType)
1712         {
1713             case QSPI_IP_HYPER_FLASH:
1714                 /* Perform alignment checking before write data */
1715                 alignedAddress = Qspi_Ip_CalcPaddingWrite(state, address, size);
1716                 /* Write data to hyper flash */
1717                 status = Qspi_Ip_HyperflashProgram(instance, alignedAddress, data, size);
1718                 break;
1719 
1720             case QSPI_IP_SERIAL_FLASH:
1721                 /* enable write before programming */
1722                 status = Qspi_Ip_WriteEnable(instance);
1723                 if (STATUS_QSPI_IP_SUCCESS == status)
1724                 {
1725                     /* Perform alignment checking before write data */
1726                     alignedAddress = Qspi_Ip_CalcPaddingWrite(state, address, size);
1727                     /* Write data to serial flash */
1728                     status = Qspi_Ip_RunWriteCommand(instance, state->configuration->writeLut, alignedAddress, data, size);
1729                 }
1730                 break;
1731             default:
1732                 status = STATUS_QSPI_IP_ERROR;
1733                 break;
1734         }
1735 
1736         if (STATUS_QSPI_IP_SUCCESS == status)
1737         {
1738             state->lastCommand = QSPI_IP_LAST_COMMAND_WRITE;
1739         }
1740     }
1741 
1742     return status;
1743 }
1744 
1745 
1746 /*FUNCTION**********************************************************************
1747  *
1748  * Function Name : Qspi_Ip_Enter0XX
1749  * Description   : Enters 0-X-X mode (no command for read instructions)
1750  * @implements     Qspi_Ip_Enter0XX_Activity */
Qspi_Ip_Enter0XX(uint32 instance)1751 Qspi_Ip_StatusType Qspi_Ip_Enter0XX(uint32 instance)
1752 {
1753 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1754     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1755 #endif
1756 
1757     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1758     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1759     uint8 dummyData;
1760 
1761     if (state->configuration->read0xxLut != QSPI_IP_LUT_INVALID)
1762     {
1763         state->activeReadLut = state->configuration->read0xxLut;
1764         /* Perform a dummy read to activate 0-X-X mode */
1765         status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, 0U, &dummyData, NULL_PTR, 1U);
1766     }
1767 
1768     if (state->configuration->read0xxLutAHB != QSPI_IP_LUT_INVALID)
1769     {
1770         /* Set 0-x-x mode LUT sequence for AHB */
1771         (void)Qspi_Ip_InitLutSeq(instance, state->configuration->read0xxLutAHB, QSPI_IP_AHB_LUT);
1772     }
1773 
1774     return status;
1775 }
1776 
1777 
1778 /*FUNCTION**********************************************************************
1779  *
1780  * Function Name : Qspi_Ip_Exit0XX
1781  * Description   : Exits 0-X-X mode (no command for read instructions)
1782  * @implements     Qspi_Ip_Exit0XX_Activity */
Qspi_Ip_Exit0XX(uint32 instance)1783 Qspi_Ip_StatusType Qspi_Ip_Exit0XX(uint32 instance)
1784 {
1785 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1786     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1787 #endif
1788 
1789     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1790     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1791     uint8 dummyData;
1792 
1793     if (state->configuration->read0xxLut != QSPI_IP_LUT_INVALID)
1794     {
1795         state->activeReadLut = state->configuration->readLut;
1796         /* Perform a dummy read to disable 0-X-X mode */
1797         status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, 0U, &dummyData, NULL_PTR, 1U);
1798     }
1799 
1800     if (state->configuration->read0xxLutAHB != QSPI_IP_LUT_INVALID)
1801     {
1802         /* Set back to normal mode LUT sequence for AHB */
1803         (void)Qspi_Ip_InitLutSeq(instance, state->configuration->readLut, QSPI_IP_AHB_LUT);
1804     }
1805 
1806     return status;
1807 }
1808 
1809 
1810 /*FUNCTION**********************************************************************
1811  *
1812  * Function Name : Qspi_Ip_SetProtection
1813  * Description   : Sets the protection bits of the device
1814  * @implements     Qspi_Ip_SetProtection_Activity */
Qspi_Ip_SetProtection(uint32 instance,uint8 value)1815 Qspi_Ip_StatusType Qspi_Ip_SetProtection(uint32 instance,
1816                                          uint8 value
1817                                         )
1818 {
1819 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1820     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1821 #endif
1822 
1823     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1824     const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
1825 
1826     return Qspi_Ip_UpdateStatusReg(instance, statusConfig->blockProtectionOffset, statusConfig->blockProtectionWidth, value);
1827 }
1828 
1829 
1830 /*FUNCTION**********************************************************************
1831  *
1832  * Function Name : Qspi_Ip_GetProtection
1833  * Description   : Returns the current protection bits of the device
1834  * @implements     Qspi_Ip_GetProtection_Activity */
Qspi_Ip_GetProtection(uint32 instance,uint8 * value)1835 Qspi_Ip_StatusType Qspi_Ip_GetProtection(uint32 instance,
1836                                          uint8 *value
1837                                         )
1838 {
1839 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1840     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1841     DEV_ASSERT_QSPI(value != NULL_PTR);
1842 #endif
1843 
1844     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1845     const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
1846 
1847     return Qspi_Ip_CheckStatusReg(instance, statusConfig->blockProtectionOffset, statusConfig->blockProtectionWidth, value);
1848 }
1849 
1850 
1851 /*FUNCTION**********************************************************************
1852  *
1853  * Function Name : Qspi_Ip_AhbReadEnable
1854  * Description   : Enables AHB reads for the current flash device
1855  * @implements     Qspi_Ip_AhbReadEnable_Activity */
Qspi_Ip_AhbReadEnable(uint32 instance)1856 Qspi_Ip_StatusType Qspi_Ip_AhbReadEnable(uint32 instance)
1857 {
1858 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1859     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1860 #endif
1861 
1862     Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1863     const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1864 
1865     if (state->activeReadLut != QSPI_IP_LUT_INVALID)
1866     {
1867         /* Patch the command sequence before using */
1868         Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1869         /* Copy sequence in LUT registers */
1870         (void)Qspi_Ip_InitLutSeq(instance, state->activeReadLut, QSPI_IP_AHB_LUT);
1871         /* Set sequence number */
1872         Qspi_Ip_SetAhbSeqId(state->connection->qspiInstance, QSPI_IP_AHB_LUT);
1873         status = STATUS_QSPI_IP_SUCCESS;
1874     }
1875 
1876     return status;
1877 }
1878 
1879 
1880 /*FUNCTION**********************************************************************
1881  *
1882  * Function Name : Qspi_Ip_Init
1883  * Description   : Initialize the serial flash memory driver
1884  *
1885  * @implements     Qspi_Ip_Init_Activity */
Qspi_Ip_Init(uint32 instance,const Qspi_Ip_MemoryConfigType * pConfig,const Qspi_Ip_MemoryConnectionType * pConnect)1886 Qspi_Ip_StatusType Qspi_Ip_Init(uint32 instance,
1887                                 const Qspi_Ip_MemoryConfigType * pConfig,
1888                                 const Qspi_Ip_MemoryConnectionType * pConnect
1889                                )
1890 {
1891     Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1892     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1893 
1894 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1895     DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1896     DEV_ASSERT_QSPI(pConfig != NULL_PTR);
1897     DEV_ASSERT_QSPI(pConnect != NULL_PTR);
1898     DEV_ASSERT_QSPI(NULL_PTR == state->configuration);
1899 #endif
1900 
1901     /* Copy configuration information to state structure */
1902     state->configuration = pConfig;
1903     state->connection = pConnect;
1904     state->activeReadLut = pConfig->readLut;    /* 0-X-X mode disabled by default */
1905     state->lastCommand = QSPI_IP_LAST_COMMAND_NONE;
1906     state->baseAddress = Qspi_Ip_GetBaseAdress(pConnect->qspiInstance, pConnect->connectionType);
1907 
1908 #if (QSPI_PERFORM_DEVICE_CONFIG == STD_ON)
1909     /* Initialize corresponding controller if required */
1910     if (pConfig->ctrlAutoCfgPtr != NULL_PTR)
1911     {
1912         status = Qspi_Ip_ControllerInit(pConnect->qspiInstance, pConfig->ctrlAutoCfgPtr);
1913     }
1914     if (STATUS_QSPI_IP_SUCCESS == status)
1915     {
1916         /* Perform initial reset */
1917         status = Qspi_Ip_InitReset(instance, pConfig->initResetSettings.resetCmdLut, pConfig->initResetSettings.resetCmdCount, state);
1918     }
1919     if (STATUS_QSPI_IP_SUCCESS == status)
1920     {
1921         /* Execute initial setup of external device */
1922         status = Qspi_Ip_InitDevice(instance, state);
1923     }
1924 
1925     /* If enabled, call the init callout, for additional QSPI IP or external memory settings. */
1926     if ((STATUS_QSPI_IP_SUCCESS == status) && (NULL_PTR != pConfig->initCallout))
1927     {
1928         status = pConfig->initCallout(instance);
1929     }
1930 
1931     /* Perform protection configuration */
1932     if (STATUS_QSPI_IP_SUCCESS == status)
1933     {
1934         status = Qspi_Ip_InitProtection(instance, state);
1935     }
1936 #endif
1937 
1938     return status;
1939 }
1940 
1941 
1942 /*FUNCTION**********************************************************************
1943  *
1944  * Function Name : Qspi_Ip_Deinit
1945  * Description   : De-initialize the serial flash memory driver
1946  * @implements     Qspi_Ip_Deinit_Activity */
Qspi_Ip_Deinit(uint32 instance)1947 Qspi_Ip_StatusType Qspi_Ip_Deinit(uint32 instance)
1948 {
1949     Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1950 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1951     DEV_ASSERT_QSPI(instance < QuadSPI_INSTANCE_COUNT);
1952     DEV_ASSERT_QSPI(state->configuration != NULL_PTR);
1953 #endif
1954 
1955     state->configuration = NULL_PTR;
1956     return STATUS_QSPI_IP_SUCCESS;
1957 }
1958 
1959 #define MEM_43_EXFLS_STOP_SEC_CODE
1960 #include "Mem_43_EXFLS_MemMap.h"
1961 
1962 #endif /* (QSPI_IP_MEM_INSTANCE_COUNT > 0) */
1963 
1964 
1965 #ifdef __cplusplus
1966 }
1967 #endif
1968 
1969 /** @} */
1970 
1971