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