1 /**
2   ******************************************************************************
3   * @file    b_u585i_iot02a_ospi.c
4   * @author  MCD Application Team
5   * @brief   This file includes a standard driver for the MX25LM51245G OSPI
6   *          memory mounted on B_U585I_IOT02A board.
7   @verbatim
8   ******************************************************************************
9   * @attention
10   *
11   * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
12   * All rights reserved.</center></h2>
13   *
14   * This software component is licensed by ST under BSD 3-Clause license,
15   * the "License"; You may not use this file except in compliance with the
16   * License. You may obtain a copy of the License at:
17   *                        opensource.org/licenses/BSD-3-Clause
18   *
19   ******************************************************************************
20 
21   ==============================================================================
22                      ##### How to use this driver #####
23   ==============================================================================
24   [..]
25    (#) This driver is used to drive the MX25LM51245G Octal NOR and the APS6408 Octal PSRAM
26        external memories mounted on B_U585I_IOT02A board.
27 
28    (#) This driver need specific component driver (MX25LM51245G and APS6408) to be included with.
29 
30    (#) MX25LM51245G Initialization steps:
31        (++) Initialize the OSPI external memory using the BSP_OSPI_NOR_Init() function. This
32             function includes the MSP layer hardware resources initialization and the
33             OSPI interface with the external memory.
34 
35    (#) MX25LM51245G Octal NOR memory operations
36        (++) OSPI memory can be accessed with read/write operations once it is
37             initialized.
38             Read/write operation can be performed with AHB access using the functions
39             BSP_OSPI_NOR_Read()/BSP_OSPI_NOR_Write().
40        (++) The function BSP_OSPI_NOR_GetInfo() returns the configuration of the OSPI memory.
41             (see the OSPI memory data sheet)
42        (++) Perform erase block operation using the function BSP_OSPI_NOR_Erase_Block() and by
43             specifying the block address. You can perform an erase operation of the whole
44             chip by calling the function BSP_OSPI_NOR_Erase_Chip().
45        (++) The function BSP_OSPI_NOR_GetStatus() returns the current status of the OSPI memory.
46             (see the OSPI memory data sheet)
47        (++) The memory access can be configured in memory-mapped mode with the call of
48             function BSP_OSPI_NOR_EnableMemoryMapped(). To go back in indirect mode, the
49             function BSP_OSPI_NOR_DisableMemoryMapped() should be used.
50        (++) The erase operation can be suspend and resume with using functions
51             BSP_OSPI_NOR_SuspendErase() and BSP_OSPI_NOR_ResumeErase()
52        (++) It is possible to put the memory in deep power-down mode to reduce its consumption.
53             For this, the function BSP_OSPI_NOR_EnterDeepPowerDown() should be called. To leave
54             the deep power-down mode, the function BSP_OSPI_NOR_LeaveDeepPowerDown() should be called.
55        (++) The function BSP_OSPI_NOR_ReadID() returns the identifier of the memory
56             (see the OSPI memory data sheet)
57        (++) The configuration of the interface between peripheral and memory is done by
58             the function BSP_OSPI_NOR_ConfigFlash(), three modes are possible :
59             - SPI : instruction, address and data on one line
60             - STR OPI : instruction, address and data on eight lines with sampling on one edge of clock
61             - DTR OPI : instruction, address and data on eight lines with sampling on both edgaes of clock
62 
63   @endverbatim
64   ******************************************************************************
65   */
66 
67 /* Includes ------------------------------------------------------------------*/
68 #include "b_u585i_iot02a_ospi.h"
69 
70 /** @addtogroup BSP
71   * @{
72   */
73 
74 /** @addtogroup B_U585I_IOT02A
75   * @{
76   */
77 
78 /** @defgroup B_U585I_IOT02A_OSPI OSPI
79   * @{
80   */
81 
82 /* Exported variables --------------------------------------------------------*/
83 /** @addtogroup B_U585I_IOT02A_OSPI_NOR_Exported_Variables
84   * @{
85   */
86 OSPI_HandleTypeDef hospi_nor[OSPI_NOR_INSTANCES_NUMBER] = {0};
87 OSPI_NOR_Ctx_t Ospi_Nor_Ctx[OSPI_NOR_INSTANCES_NUMBER] = {{
88     OSPI_ACCESS_NONE,
89     MX25LM51245G_SPI_MODE,
90     MX25LM51245G_STR_TRANSFER
91   }
92 };
93 /**
94   * @}
95   */
96 
97 /* Exported variables --------------------------------------------------------*/
98 
99 
100 /**
101   * @}
102   */
103 
104 /* Private constants --------------------------------------------------------*/
105 /* Private variables ---------------------------------------------------------*/
106 /** @defgroup B_U585I_IOT02A_OSPI_NOR_Private_Variables OSPI_NOR Private Variables
107   * @{
108   */
109 #if (USE_HAL_OSPI_REGISTER_CALLBACKS == 1)
110 static uint32_t OspiNor_IsMspCbValid[OSPI_NOR_INSTANCES_NUMBER] = {0};
111 #endif /* USE_HAL_OSPI_REGISTER_CALLBACKS */
112 /**
113   * @}
114   */
115 
116 /** @defgroup B_U585I_IOT02A_OSPI_RAM_Private_Variables OSPI_RAM Private Variables
117   * @{
118   */
119 #if (USE_HAL_OSPI_REGISTER_CALLBACKS == 1)
120 static uint32_t OspiRam_IsMspCbValid[OSPI_RAM_INSTANCES_NUMBER] = {0};
121 #endif /* USE_HAL_OSPI_REGISTER_CALLBACKS */
122 /**
123   * @}
124   */
125 /* Private functions ---------------------------------------------------------*/
126 
127 /** @defgroup B-U585I-IOT02A_OSPI_NOR_Private_Functions OSPI_NOR Private Functions
128   * @{
129   */
130 static void    OSPI_NOR_MspInit(OSPI_HandleTypeDef *hospi);
131 static void    OSPI_NOR_MspDeInit(OSPI_HandleTypeDef *hospi);
132 static int32_t OSPI_NOR_ResetMemory(uint32_t Instance);
133 static int32_t OSPI_NOR_EnterDOPIMode(uint32_t Instance);
134 static int32_t OSPI_NOR_EnterSOPIMode(uint32_t Instance);
135 static int32_t OSPI_NOR_ExitOPIMode(uint32_t Instance);
136 /**
137   * @}
138   */
139 
140 
141 /* Exported functions ---------------------------------------------------------*/
142 static int32_t OSPI_DLYB_Enable(OSPI_HandleTypeDef *hospi);
143 /** @addtogroup B_U585I_IOT02A_OSPI_NOR_Exported_Functions
144   * @{
145   */
146 
147 /**
148   * @brief  Initializes the OSPI interface.
149   * @param  Instance   OSPI Instance
150   * @param  Init       OSPI Init structure
151   * @retval BSP status
152   */
BSP_OSPI_NOR_Init(uint32_t Instance,BSP_OSPI_NOR_Init_t * Init)153 int32_t BSP_OSPI_NOR_Init(uint32_t Instance, BSP_OSPI_NOR_Init_t *Init)
154 {
155   int32_t ret;
156   BSP_OSPI_NOR_Info_t pInfo;
157   MX_OSPI_InitTypeDef ospi_init;
158 
159   /* Check if the instance is supported */
160   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
161   {
162     ret = BSP_ERROR_WRONG_PARAM;
163   }
164   else
165   {
166     /* Check if the instance is already initialized */
167     if (Ospi_Nor_Ctx[Instance].IsInitialized == OSPI_ACCESS_NONE)
168     {
169 #if (USE_HAL_OSPI_REGISTER_CALLBACKS == 0)
170       /* Msp OSPI initialization */
171       OSPI_NOR_MspInit(&hospi_nor[Instance]);
172 #else
173       /* Register the OSPI MSP Callbacks */
174       if (OspiNor_IsMspCbValid[Instance] == 0UL)
175       {
176         if (BSP_OSPI_NOR_RegisterDefaultMspCallbacks(Instance) != BSP_ERROR_NONE)
177         {
178           return BSP_ERROR_PERIPH_FAILURE;
179         }
180       }
181 #endif /* USE_HAL_OSPI_REGISTER_CALLBACKS */
182 
183       /* Get Flash information of one memory */
184       (void)MX25LM51245G_GetFlashInfo(&pInfo);
185 
186       /* Fill config structure */
187       ospi_init.ClockPrescaler = 4; /* OctoSPI clock = 160MHz / ClockPrescaler = 40MHz */
188       ospi_init.MemorySize     = (uint32_t)POSITION_VAL((uint32_t)pInfo.FlashSize);
189       ospi_init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
190       ospi_init.TransferRate   = (uint32_t)Init->TransferRate;
191 
192       /* STM32 OSPI interface initialization */
193       if (MX_OSPI_NOR_Init(&hospi_nor[Instance], &ospi_init) != HAL_OK)
194       {
195         ret = BSP_ERROR_PERIPH_FAILURE;
196       }
197       /* OSPI Delay Block enable */
198       else if (OSPI_DLYB_Enable(&hospi_nor[Instance]) != BSP_ERROR_NONE)
199       {
200         ret = BSP_ERROR_COMPONENT_FAILURE;
201       }
202       /* OSPI memory reset */
203       else if (OSPI_NOR_ResetMemory(Instance) != BSP_ERROR_NONE)
204       {
205         ret = BSP_ERROR_COMPONENT_FAILURE;
206       }
207       /* Check if memory is ready */
208       else if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
209                                                 Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
210       {
211         ret = BSP_ERROR_COMPONENT_FAILURE;
212       }
213       /* Configure the memory */
214       else if (BSP_OSPI_NOR_ConfigFlash(Instance, Init->InterfaceMode, Init->TransferRate) != BSP_ERROR_NONE)
215       {
216         ret = BSP_ERROR_COMPONENT_FAILURE;
217       }
218       else
219       {
220         ret = BSP_ERROR_NONE;
221       }
222     }
223     else
224     {
225       ret = BSP_ERROR_NONE;
226     }
227   }
228 
229   /* Return BSP status */
230   return ret;
231 }
232 
233 /**
234   * @brief  De-Initializes the OSPI interface.
235   * @param  Instance   OSPI Instance
236   * @retval BSP status
237   */
BSP_OSPI_NOR_DeInit(uint32_t Instance)238 int32_t BSP_OSPI_NOR_DeInit(uint32_t Instance)
239 {
240   int32_t ret = BSP_ERROR_NONE;
241 
242   /* Check if the instance is supported */
243   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
244   {
245     ret = BSP_ERROR_WRONG_PARAM;
246   }
247   else
248   {
249     /* Check if the instance is already initialized */
250     if (Ospi_Nor_Ctx[Instance].IsInitialized != OSPI_ACCESS_NONE)
251     {
252       /* Disable Memory mapped mode */
253       if (Ospi_Nor_Ctx[Instance].IsInitialized == OSPI_ACCESS_MMP)
254       {
255         if (BSP_OSPI_NOR_DisableMemoryMappedMode(Instance) != BSP_ERROR_NONE)
256         {
257           return BSP_ERROR_COMPONENT_FAILURE;
258         }
259       }
260 
261       /* Set default Ospi_Nor_Ctx values */
262       Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_NONE;
263       Ospi_Nor_Ctx[Instance].InterfaceMode = BSP_OSPI_NOR_SPI_MODE;
264       Ospi_Nor_Ctx[Instance].TransferRate  = BSP_OSPI_NOR_STR_TRANSFER;
265 
266 #if (USE_HAL_OSPI_REGISTER_CALLBACKS == 0)
267       OSPI_NOR_MspDeInit(&hospi_nor[Instance]);
268 #endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS == 0) */
269 
270       /* Call the DeInit function to reset the driver */
271       if (HAL_OSPI_DeInit(&hospi_nor[Instance]) != HAL_OK)
272       {
273         ret = BSP_ERROR_PERIPH_FAILURE;
274       }
275     }
276   }
277 
278   /* Return BSP status */
279   return ret;
280 }
281 
282 /**
283   * @brief  Initializes the OSPI interface.
284   * @param  hospi          OSPI handle
285   * @param  Init           OSPI config structure
286   * @retval BSP status
287   */
MX_OSPI_NOR_Init(OSPI_HandleTypeDef * hospi,MX_OSPI_InitTypeDef * Init)288 __weak HAL_StatusTypeDef MX_OSPI_NOR_Init(OSPI_HandleTypeDef *hospi, MX_OSPI_InitTypeDef *Init)
289 {
290   /* OctoSPI initialization */
291   hospi->Instance = OCTOSPI2;
292 
293   hospi->Init.FifoThreshold      = 4;
294   hospi->Init.DualQuad           = HAL_OSPI_DUALQUAD_DISABLE;
295   hospi->Init.DeviceSize         = Init->MemorySize; /* 512 MBits */
296   hospi->Init.ChipSelectHighTime = 2;
297   hospi->Init.FreeRunningClock   = HAL_OSPI_FREERUNCLK_ENABLE;
298   hospi->Init.ClockMode          = HAL_OSPI_CLOCK_MODE_0;
299   hospi->Init.WrapSize           = HAL_OSPI_WRAP_NOT_SUPPORTED;
300   hospi->Init.ClockPrescaler     = Init->ClockPrescaler;
301   hospi->Init.SampleShifting     = Init->SampleShifting;
302   hospi->Init.ChipSelectBoundary = 0;
303 
304   if (Init->TransferRate == (uint32_t) BSP_OSPI_NOR_DTR_TRANSFER)
305   {
306     hospi->Init.MemoryType            = HAL_OSPI_MEMTYPE_MACRONIX;
307     hospi->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
308   }
309   else
310   {
311     hospi->Init.MemoryType            = HAL_OSPI_MEMTYPE_MICRON;
312     hospi->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
313   }
314 
315   return HAL_OSPI_Init(hospi);
316 }
317 
318 #if (USE_HAL_OSPI_REGISTER_CALLBACKS == 1)
319 /**
320   * @brief Default BSP OSPI Msp Callbacks
321   * @param Instance      OSPI Instance
322   * @retval BSP status
323   */
BSP_OSPI_NOR_RegisterDefaultMspCallbacks(uint32_t Instance)324 int32_t BSP_OSPI_NOR_RegisterDefaultMspCallbacks(uint32_t Instance)
325 {
326   int32_t ret = BSP_ERROR_NONE;
327 
328   /* Check if the instance is supported */
329   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
330   {
331     ret = BSP_ERROR_WRONG_PARAM;
332   }
333   else
334   {
335     /* Register MspInit/MspDeInit Callbacks */
336     if (HAL_OSPI_RegisterCallback(&hospi_nor[Instance], HAL_OSPI_MSP_INIT_CB_ID, OSPI_NOR_MspInit) != HAL_OK)
337     {
338       ret = BSP_ERROR_PERIPH_FAILURE;
339     }
340     else if (HAL_OSPI_RegisterCallback(&hospi_nor[Instance], HAL_OSPI_MSP_DEINIT_CB_ID, OSPI_NOR_MspDeInit) != HAL_OK)
341     {
342       ret = BSP_ERROR_PERIPH_FAILURE;
343     }
344     else
345     {
346       OspiNor_IsMspCbValid[Instance] = 1U;
347     }
348   }
349 
350   /* Return BSP status */
351   return ret;
352 }
353 
354 /**
355   * @brief BSP OSPI Msp Callback registering
356   * @param Instance     OSPI Instance
357   * @param CallBacks    pointer to MspInit/MspDeInit callbacks functions
358   * @retval BSP status
359   */
BSP_OSPI_NOR_RegisterMspCallbacks(uint32_t Instance,BSP_OSPI_Cb_t * CallBacks)360 int32_t BSP_OSPI_NOR_RegisterMspCallbacks(uint32_t Instance, BSP_OSPI_Cb_t *CallBacks)
361 {
362   int32_t ret = BSP_ERROR_NONE;
363 
364   /* Check if the instance is supported */
365   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
366   {
367     ret = BSP_ERROR_WRONG_PARAM;
368   }
369   else
370   {
371     /* Register MspInit/MspDeInit Callbacks */
372     if (HAL_OSPI_RegisterCallback(&hospi_nor[Instance], HAL_OSPI_MSP_INIT_CB_ID, CallBacks->pMspInitCb) != HAL_OK)
373     {
374       ret = BSP_ERROR_PERIPH_FAILURE;
375     }
376     else if (HAL_OSPI_RegisterCallback(&hospi_nor[Instance],
377                                        HAL_OSPI_MSP_DEINIT_CB_ID, CallBacks->pMspDeInitCb) != HAL_OK)
378     {
379       ret = BSP_ERROR_PERIPH_FAILURE;
380     }
381     else
382     {
383       OspiNor_IsMspCbValid[Instance] = 1U;
384     }
385   }
386 
387   /* Return BSP status */
388   return ret;
389 }
390 #endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS == 1) */
391 
392 /**
393   * @brief  Reads an amount of data from the OSPI memory.
394   * @param  Instance  OSPI instance
395   * @param  pData     Pointer to data to be read
396   * @param  ReadAddr  Read start address
397   * @param  Size      Size of data to read
398   * @retval BSP status
399   */
BSP_OSPI_NOR_Read(uint32_t Instance,uint8_t * pData,uint32_t ReadAddr,uint32_t Size)400 int32_t BSP_OSPI_NOR_Read(uint32_t Instance, uint8_t *pData, uint32_t ReadAddr, uint32_t Size)
401 {
402   int32_t ret;
403 
404   /* Check if the instance is supported */
405   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
406   {
407     ret = BSP_ERROR_WRONG_PARAM;
408   }
409   else
410   {
411     if (Ospi_Nor_Ctx[Instance].TransferRate == BSP_OSPI_NOR_STR_TRANSFER)
412     {
413       if (MX25LM51245G_ReadSTR(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
414                                MX25LM51245G_4BYTES_SIZE, pData, ReadAddr, Size) != MX25LM51245G_OK)
415       {
416         ret = BSP_ERROR_COMPONENT_FAILURE;
417       }
418       else
419       {
420         ret = BSP_ERROR_NONE;
421       }
422     }
423     else
424     {
425       if (MX25LM51245G_ReadDTR(&hospi_nor[Instance], pData, ReadAddr, Size) != MX25LM51245G_OK)
426       {
427         ret = BSP_ERROR_COMPONENT_FAILURE;
428       }
429       else
430       {
431         ret = BSP_ERROR_NONE;
432       }
433     }
434   }
435 
436   /* Return BSP status */
437   return ret;
438 }
439 
440 /**
441   * @brief  Writes an amount of data to the OSPI memory.
442   * @param  Instance  OSPI instance
443   * @param  pData     Pointer to data to be written
444   * @param  WriteAddr Write start address
445   * @param  Size      Size of data to write
446   * @retval BSP status
447   */
BSP_OSPI_NOR_Write(uint32_t Instance,uint8_t * pData,uint32_t WriteAddr,uint32_t Size)448 int32_t BSP_OSPI_NOR_Write(uint32_t Instance, uint8_t *pData, uint32_t WriteAddr, uint32_t Size)
449 {
450   int32_t ret = BSP_ERROR_NONE;
451   uint32_t end_addr;
452   uint32_t current_size;
453   uint32_t current_addr;
454   uint32_t data_addr;
455 
456   /* Check if the instance is supported */
457   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
458   {
459     ret = BSP_ERROR_WRONG_PARAM;
460   }
461   else
462   {
463     /* Calculation of the size between the write address and the end of the page */
464     current_size = MX25LM51245G_PAGE_SIZE - (WriteAddr % MX25LM51245G_PAGE_SIZE);
465 
466     /* Check if the size of the data is less than the remaining place in the page */
467     if (current_size > Size)
468     {
469       current_size = Size;
470     }
471 
472     /* Initialize the address variables */
473     current_addr = WriteAddr;
474     end_addr = WriteAddr + Size;
475     data_addr = (uint32_t)pData;
476 
477     /* Perform the write page by page */
478     do
479     {
480       /* Check if Flash busy ? */
481       if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
482                                            Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
483       {
484         ret = BSP_ERROR_COMPONENT_FAILURE;
485       }/* Enable write operations */
486       else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
487                                         Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
488       {
489         ret = BSP_ERROR_COMPONENT_FAILURE;
490       }
491       else
492       {
493         if (Ospi_Nor_Ctx[Instance].TransferRate == BSP_OSPI_NOR_STR_TRANSFER)
494         {
495           /* Issue page program command */
496           if (MX25LM51245G_PageProgram(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
497                                        MX25LM51245G_4BYTES_SIZE, (uint8_t *)data_addr, current_addr,
498                                        current_size) != MX25LM51245G_OK)
499           {
500             ret = BSP_ERROR_COMPONENT_FAILURE;
501           }
502         }
503         else
504         {
505           /* Issue page program command */
506           if (MX25LM51245G_PageProgramDTR(&hospi_nor[Instance], (uint8_t *)data_addr, current_addr,
507                                           current_size) != MX25LM51245G_OK)
508           {
509             ret = BSP_ERROR_COMPONENT_FAILURE;
510           }
511         }
512 
513         if (ret == BSP_ERROR_NONE)
514         {
515           /* Configure automatic polling mode to wait for end of program */
516           if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
517                                                Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
518           {
519             ret = BSP_ERROR_COMPONENT_FAILURE;
520           }
521           else
522           {
523             /* Update the address and size variables for next page programming */
524             current_addr += current_size;
525             data_addr += current_size;
526             current_size = ((current_addr + MX25LM51245G_PAGE_SIZE) > end_addr)
527                            ? (end_addr - current_addr)
528                            : MX25LM51245G_PAGE_SIZE;
529           }
530         }
531       }
532     } while ((current_addr < end_addr) && (ret == BSP_ERROR_NONE));
533   }
534 
535   /* Return BSP status */
536   return ret;
537 }
538 
539 /**
540   * @brief  Erases the specified block of the OSPI memory.
541   * @param  Instance     OSPI instance
542   * @param  BlockAddress Block address to erase
543   * @param  BlockSize    Erase Block size
544   * @retval BSP status
545   */
BSP_OSPI_NOR_Erase_Block(uint32_t Instance,uint32_t BlockAddress,BSP_OSPI_NOR_Erase_t BlockSize)546 int32_t BSP_OSPI_NOR_Erase_Block(uint32_t Instance, uint32_t BlockAddress, BSP_OSPI_NOR_Erase_t BlockSize)
547 {
548   int32_t ret;
549 
550   /* Check if the instance is supported */
551   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
552   {
553     ret = BSP_ERROR_WRONG_PARAM;
554   }
555   else
556   {
557     /* Check Flash busy ? */
558     if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
559                                          Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
560     {
561       ret = BSP_ERROR_COMPONENT_FAILURE;
562     }/* Enable write operations */
563     else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
564                                       Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
565     {
566       ret = BSP_ERROR_COMPONENT_FAILURE;
567     }/* Issue Block Erase command */
568     else if (MX25LM51245G_BlockErase(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
569                                      Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_4BYTES_SIZE,
570                                      BlockAddress, BlockSize) != MX25LM51245G_OK)
571     {
572       ret = BSP_ERROR_COMPONENT_FAILURE;
573     }
574     else
575     {
576       ret = BSP_ERROR_NONE;
577     }
578   }
579 
580   /* Return BSP status */
581   return ret;
582 }
583 
584 /**
585   * @brief  Erases the entire OSPI memory.
586   * @param  Instance  OSPI instance
587   * @retval BSP status
588   */
BSP_OSPI_NOR_Erase_Chip(uint32_t Instance)589 int32_t BSP_OSPI_NOR_Erase_Chip(uint32_t Instance)
590 {
591   int32_t ret;
592 
593   /* Check if the instance is supported */
594   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
595   {
596     ret = BSP_ERROR_WRONG_PARAM;
597   }
598   else
599   {
600     /* Check Flash busy ? */
601     if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
602                                          Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
603     {
604       ret = BSP_ERROR_COMPONENT_FAILURE;
605     }/* Enable write operations */
606     else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
607                                       Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
608     {
609       ret = BSP_ERROR_COMPONENT_FAILURE;
610     }/* Issue Chip erase command */
611     else if (MX25LM51245G_BlockErase(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
612                                      Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_4BYTES_SIZE, 0,
613                                      MX25LM51245G_ERASE_BULK) != MX25LM51245G_OK)
614     {
615       ret = BSP_ERROR_COMPONENT_FAILURE;
616     }
617     else
618     {
619       ret = BSP_ERROR_NONE;
620     }
621   }
622 
623   /* Return BSP status */
624   return ret;
625 }
626 
627 /**
628   * @brief  Reads current status of the OSPI memory.
629   * @param  Instance  OSPI instance
630   * @retval OSPI memory status: whether busy or not
631   */
BSP_OSPI_NOR_GetStatus(uint32_t Instance)632 int32_t BSP_OSPI_NOR_GetStatus(uint32_t Instance)
633 {
634   static uint8_t reg[2];
635   int32_t ret;
636 
637   /* Check if the instance is supported */
638   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
639   {
640     ret = BSP_ERROR_WRONG_PARAM;
641   }
642   else
643   {
644     if (MX25LM51245G_ReadSecurityRegister(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
645                                           Ospi_Nor_Ctx[Instance].TransferRate, reg) != MX25LM51245G_OK)
646     {
647       ret = BSP_ERROR_COMPONENT_FAILURE;
648     }/* Check the value of the register */
649     else if ((reg[0] & (MX25LM51245G_SECR_P_FAIL | MX25LM51245G_SECR_E_FAIL)) != 0U)
650     {
651       ret = BSP_ERROR_COMPONENT_FAILURE;
652     }
653     else if ((reg[0] & (MX25LM51245G_SECR_PSB | MX25LM51245G_SECR_ESB)) != 0U)
654     {
655       ret = BSP_ERROR_OSPI_SUSPENDED;
656     }
657     else if (MX25LM51245G_ReadStatusRegister(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
658                                              Ospi_Nor_Ctx[Instance].TransferRate, reg) != MX25LM51245G_OK)
659     {
660       ret = BSP_ERROR_COMPONENT_FAILURE;
661     }/* Check the value of the register */
662     else if ((reg[0] & MX25LM51245G_SR_WIP) != 0U)
663     {
664       ret = BSP_ERROR_BUSY;
665     }
666     else
667     {
668       ret = BSP_ERROR_NONE;
669     }
670   }
671 
672   /* Return BSP status */
673   return ret;
674 }
675 
676 /**
677   * @brief  Return the configuration of the OSPI memory.
678   * @param  Instance  OSPI instance
679   * @param  pInfo     pointer on the configuration structure
680   * @retval BSP status
681   */
BSP_OSPI_NOR_GetInfo(uint32_t Instance,BSP_OSPI_NOR_Info_t * pInfo)682 int32_t BSP_OSPI_NOR_GetInfo(uint32_t Instance, BSP_OSPI_NOR_Info_t *pInfo)
683 {
684   int32_t ret = BSP_ERROR_NONE;
685 
686   /* Check if the instance is supported */
687   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
688   {
689     ret = BSP_ERROR_WRONG_PARAM;
690   }
691   else
692   {
693     (void)MX25LM51245G_GetFlashInfo(pInfo);
694   }
695 
696   /* Return BSP status */
697   return ret;
698 }
699 
700 /**
701   * @brief  Configure the OSPI in memory-mapped mode
702   * @param  Instance  OSPI instance
703   * @retval BSP status
704   */
BSP_OSPI_NOR_EnableMemoryMappedMode(uint32_t Instance)705 int32_t BSP_OSPI_NOR_EnableMemoryMappedMode(uint32_t Instance)
706 {
707   int32_t ret = BSP_ERROR_NONE;
708 
709   /* Check if the instance is supported */
710   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
711   {
712     ret = BSP_ERROR_WRONG_PARAM;
713   }
714   else
715   {
716     if (Ospi_Nor_Ctx[Instance].TransferRate == BSP_OSPI_NOR_STR_TRANSFER)
717     {
718       if (MX25LM51245G_EnableMemoryMappedModeSTR(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
719                                                  MX25LM51245G_4BYTES_SIZE) != MX25LM51245G_OK)
720       {
721         ret = BSP_ERROR_COMPONENT_FAILURE;
722       }
723       else /* Update OSPI context if all operations are well done */
724       {
725         Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_MMP;
726       }
727     }
728     else
729     {
730       if (MX25LM51245G_EnableMemoryMappedModeDTR(&hospi_nor[Instance],
731                                                  Ospi_Nor_Ctx[Instance].InterfaceMode) != MX25LM51245G_OK)
732       {
733         ret = BSP_ERROR_COMPONENT_FAILURE;
734       }
735       else /* Update OSPI context if all operations are well done */
736       {
737         Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_MMP;
738       }
739     }
740   }
741 
742   /* Return BSP status */
743   return ret;
744 }
745 
746 /**
747   * @brief  Exit form memory-mapped mode
748   *         Only 1 Instance can running MMP mode. And it will lock system at this mode.
749   * @param  Instance  OSPI instance
750   * @retval BSP status
751   */
BSP_OSPI_NOR_DisableMemoryMappedMode(uint32_t Instance)752 int32_t BSP_OSPI_NOR_DisableMemoryMappedMode(uint32_t Instance)
753 {
754   int32_t ret = BSP_ERROR_NONE;
755 
756   /* Check if the instance is supported */
757   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
758   {
759     ret = BSP_ERROR_WRONG_PARAM;
760   }
761   else
762   {
763     if (Ospi_Nor_Ctx[Instance].IsInitialized != OSPI_ACCESS_MMP)
764     {
765       ret = BSP_ERROR_OSPI_MMP_UNLOCK_FAILURE;
766     }/* Abort MMP back to indirect mode */
767     else if (HAL_OSPI_Abort(&hospi_nor[Instance]) != HAL_OK)
768     {
769       ret = BSP_ERROR_PERIPH_FAILURE;
770     }
771     else /* Update OSPI NOR context if all operations are well done */
772     {
773       Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_INDIRECT;
774     }
775   }
776 
777   /* Return BSP status */
778   return ret;
779 }
780 
781 /**
782   * @brief  Get flash ID 3 Bytes:
783   *         Manufacturer ID, Memory type, Memory density
784   * @param  Instance  OSPI instance
785   * @param  Id Pointer to flash ID bytes
786   * @retval BSP status
787   */
BSP_OSPI_NOR_ReadID(uint32_t Instance,uint8_t * Id)788 int32_t BSP_OSPI_NOR_ReadID(uint32_t Instance, uint8_t *Id)
789 {
790   int32_t ret;
791 
792   /* Check if the instance is supported */
793   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
794   {
795     ret = BSP_ERROR_WRONG_PARAM;
796   }
797   else if (MX25LM51245G_ReadID(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
798                                Ospi_Nor_Ctx[Instance].TransferRate, Id) != MX25LM51245G_OK)
799   {
800     ret = BSP_ERROR_COMPONENT_FAILURE;
801   }
802   else
803   {
804     ret = BSP_ERROR_NONE;
805   }
806 
807   /* Return BSP status */
808   return ret;
809 }
810 
811 /**
812   * @brief  Set Flash to desired Interface mode. And this instance becomes current instance.
813   *         If current instance running at MMP mode then this function doesn't work.
814   *         Indirect -> Indirect
815   * @param  Instance  OSPI instance
816   * @param  Mode      OSPI mode
817   * @param  Rate      OSPI transfer rate
818   * @retval BSP status
819   */
BSP_OSPI_NOR_ConfigFlash(uint32_t Instance,BSP_OSPI_NOR_Interface_t Mode,BSP_OSPI_NOR_Transfer_t Rate)820 int32_t BSP_OSPI_NOR_ConfigFlash(uint32_t Instance, BSP_OSPI_NOR_Interface_t Mode, BSP_OSPI_NOR_Transfer_t Rate)
821 {
822   int32_t ret = BSP_ERROR_NONE;
823 
824   /* Check if the instance is supported */
825   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
826   {
827     ret = BSP_ERROR_WRONG_PARAM;
828   }
829   else
830   {
831     /* Check if MMP mode locked ************************************************/
832     if (Ospi_Nor_Ctx[Instance].IsInitialized == OSPI_ACCESS_MMP)
833     {
834       ret = BSP_ERROR_OSPI_MMP_LOCK_FAILURE;
835     }
836     else
837     {
838       /* Setup Flash interface ***************************************************/
839       switch (Ospi_Nor_Ctx[Instance].InterfaceMode)
840       {
841         case BSP_OSPI_NOR_OPI_MODE :  /* 8-8-8 commands */
842           if ((Mode != BSP_OSPI_NOR_OPI_MODE) || (Rate != Ospi_Nor_Ctx[Instance].TransferRate))
843           {
844             /* Exit OPI mode */
845             ret = OSPI_NOR_ExitOPIMode(Instance);
846 
847             if ((ret == BSP_ERROR_NONE) && (Mode == BSP_OSPI_NOR_OPI_MODE))
848             {
849 
850               if (Ospi_Nor_Ctx[Instance].TransferRate == BSP_OSPI_NOR_STR_TRANSFER)
851               {
852                 /* Enter DTR OPI mode */
853                 ret = OSPI_NOR_EnterDOPIMode(Instance);
854               }
855               else
856               {
857                 /* Enter STR OPI mode */
858                 ret = OSPI_NOR_EnterSOPIMode(Instance);
859               }
860             }
861           }
862           break;
863 
864         case BSP_OSPI_NOR_SPI_MODE :  /* 1-1-1 commands, Power on H/W default setting */
865         default :
866           if (Mode == BSP_OSPI_NOR_OPI_MODE)
867           {
868             if (Rate == BSP_OSPI_NOR_STR_TRANSFER)
869             {
870               /* Enter STR OPI mode */
871               ret = OSPI_NOR_EnterSOPIMode(Instance);
872             }
873             else
874             {
875               /* Enter DTR OPI mode */
876               ret = OSPI_NOR_EnterDOPIMode(Instance);
877             }
878           }
879           break;
880       }
881 
882       /* Update OSPI context if all operations are well done */
883       if (ret == BSP_ERROR_NONE)
884       {
885         /* Update current status parameter *****************************************/
886         Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_INDIRECT;
887         Ospi_Nor_Ctx[Instance].InterfaceMode = Mode;
888         Ospi_Nor_Ctx[Instance].TransferRate  = Rate;
889       }
890     }
891   }
892 
893   /* Return BSP status */
894   return ret;
895 }
896 
897 /**
898   * @brief  This function suspends an ongoing erase command.
899   * @param  Instance  OSPI instance
900   * @retval BSP status
901   */
BSP_OSPI_NOR_SuspendErase(uint32_t Instance)902 int32_t BSP_OSPI_NOR_SuspendErase(uint32_t Instance)
903 {
904   int32_t ret;
905 
906   /* Check if the instance is supported */
907   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
908   {
909     ret = BSP_ERROR_WRONG_PARAM;
910   }
911   /* Check whether the device is busy (erase operation is in progress). */
912   else if (BSP_OSPI_NOR_GetStatus(Instance) != BSP_ERROR_BUSY)
913   {
914     ret = BSP_ERROR_COMPONENT_FAILURE;
915   }
916   else if (MX25LM51245G_Suspend(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
917                                 Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
918   {
919     ret = BSP_ERROR_COMPONENT_FAILURE;
920   }
921   else if (BSP_OSPI_NOR_GetStatus(Instance) != BSP_ERROR_OSPI_SUSPENDED)
922   {
923     ret = BSP_ERROR_COMPONENT_FAILURE;
924   }
925   else
926   {
927     ret = BSP_ERROR_NONE;
928   }
929 
930   /* Return BSP status */
931   return ret;
932 }
933 
934 /**
935   * @brief  This function resumes a paused erase command.
936   * @param  Instance  OSPI instance
937   * @retval BSP status
938   */
BSP_OSPI_NOR_ResumeErase(uint32_t Instance)939 int32_t BSP_OSPI_NOR_ResumeErase(uint32_t Instance)
940 {
941   int32_t ret;
942 
943   /* Check if the instance is supported */
944   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
945   {
946     ret = BSP_ERROR_WRONG_PARAM;
947   }
948   /* Check whether the device is busy (erase operation is in progress). */
949   else if (BSP_OSPI_NOR_GetStatus(Instance) != BSP_ERROR_OSPI_SUSPENDED)
950   {
951     ret = BSP_ERROR_COMPONENT_FAILURE;
952   }
953   else if (MX25LM51245G_Resume(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
954                                Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
955   {
956     ret = BSP_ERROR_COMPONENT_FAILURE;
957   }
958   /*
959   When this command is executed, the status register write in progress bit is set to 1, and
960   the flag status register program erase controller bit is set to 0. This command is ignored
961   if the device is not in a suspended state.
962   */
963   else if (BSP_OSPI_NOR_GetStatus(Instance) != BSP_ERROR_BUSY)
964   {
965     ret = BSP_ERROR_COMPONENT_FAILURE;
966   }
967   else
968   {
969     ret = BSP_ERROR_NONE;
970   }
971 
972   /* Return BSP status */
973   return ret;
974 }
975 
976 /**
977   * @brief  This function enter the OSPI memory in deep power down mode.
978   * @param  Instance  OSPI instance
979   * @retval BSP status
980   */
BSP_OSPI_NOR_EnterDeepPowerDown(uint32_t Instance)981 int32_t BSP_OSPI_NOR_EnterDeepPowerDown(uint32_t Instance)
982 {
983   int32_t ret;
984 
985   /* Check if the instance is supported */
986   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
987   {
988     ret = BSP_ERROR_WRONG_PARAM;
989   }
990   else if (MX25LM51245G_EnterPowerDown(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
991                                        Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
992   {
993     ret = BSP_ERROR_COMPONENT_FAILURE;
994   }
995   else
996   {
997     ret = BSP_ERROR_NONE;
998   }
999 
1000   /* ---          Memory takes 10us max to enter deep power down          --- */
1001 
1002   /* Return BSP status */
1003   return ret;
1004 }
1005 
1006 /**
1007   * @brief  This function leave the OSPI memory from deep power down mode.
1008   * @param  Instance  OSPI instance
1009   * @retval BSP status
1010   */
BSP_OSPI_NOR_LeaveDeepPowerDown(uint32_t Instance)1011 int32_t BSP_OSPI_NOR_LeaveDeepPowerDown(uint32_t Instance)
1012 {
1013   int32_t ret;
1014 
1015   /* Check if the instance is supported */
1016   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
1017   {
1018     ret = BSP_ERROR_WRONG_PARAM;
1019   }
1020   else if (MX25LM51245G_NoOperation(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1021                                     Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
1022   {
1023     ret = BSP_ERROR_COMPONENT_FAILURE;
1024   }
1025   else
1026   {
1027     ret = BSP_ERROR_NONE;
1028   }
1029 
1030   /* --- A NOP command is sent to the memory, as the nCS should be low for at least 20 ns --- */
1031   /* ---                  Memory takes 30us min to leave deep power down                  --- */
1032 
1033   /* Return BSP status */
1034   return ret;
1035 }
1036 /**
1037   * @}
1038   */
1039 
1040 
1041 
1042 /** @addtogroup B-U585I-IOT02A_OSPI_NOR_Private_Functions
1043   * @{
1044   */
1045 
1046 /**
1047   * @brief  Initializes the OSPI MSP.
1048   * @param  hospi OSPI handle
1049   * @retval None
1050   */
OSPI_NOR_MspInit(OSPI_HandleTypeDef * hospi)1051 static void OSPI_NOR_MspInit(OSPI_HandleTypeDef *hospi)
1052 {
1053   GPIO_InitTypeDef GPIO_InitStruct;
1054 
1055   /* hospi unused argument(s) compilation warning */
1056   UNUSED(hospi);
1057 
1058   /* Enable the OctoSPI memory interface clock */
1059   OSPI_NOR_CLK_ENABLE();
1060 
1061   /* Reset the OctoSPI memory interface */
1062   OSPI_NOR_FORCE_RESET();
1063   OSPI_NOR_RELEASE_RESET();
1064 
1065   /* Enable GPIO clocks */
1066   OSPI_NOR_CLK_GPIO_CLK_ENABLE();
1067   OSPI_NOR_DQS_GPIO_CLK_ENABLE();
1068   OSPI_NOR_CS_GPIO_CLK_ENABLE();
1069   OSPI_NOR_D0_GPIO_CLK_ENABLE();
1070   OSPI_NOR_D1_GPIO_CLK_ENABLE();
1071   OSPI_NOR_D2_GPIO_CLK_ENABLE();
1072   OSPI_NOR_D3_GPIO_CLK_ENABLE();
1073   OSPI_NOR_D4_GPIO_CLK_ENABLE();
1074   OSPI_NOR_D5_GPIO_CLK_ENABLE();
1075   OSPI_NOR_D6_GPIO_CLK_ENABLE();
1076   OSPI_NOR_D7_GPIO_CLK_ENABLE();
1077 
1078   /* OctoSPI CS GPIO pin configuration  */
1079   GPIO_InitStruct.Pin       = OSPI_NOR_CS_PIN;
1080   GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
1081   GPIO_InitStruct.Pull      = GPIO_PULLUP;
1082   GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
1083   GPIO_InitStruct.Alternate = OSPI_NOR_CS_PIN_AF;
1084   HAL_GPIO_Init(OSPI_NOR_CS_GPIO_PORT, &GPIO_InitStruct);
1085 
1086   /* OctoSPI DQS GPIO pin configuration  */
1087   GPIO_InitStruct.Pin       = OSPI_NOR_DQS_PIN;
1088   GPIO_InitStruct.Alternate = OSPI_NOR_DQS_PIN_AF;
1089   HAL_GPIO_Init(OSPI_NOR_DQS_GPIO_PORT, &GPIO_InitStruct);
1090 
1091   /* OctoSPI CLK GPIO pin configuration  */
1092   GPIO_InitStruct.Pin       = OSPI_NOR_CLK_PIN;
1093   GPIO_InitStruct.Pull      = GPIO_NOPULL;
1094   GPIO_InitStruct.Alternate = OSPI_NOR_CLK_PIN_AF;
1095   HAL_GPIO_Init(OSPI_NOR_CLK_GPIO_PORT, &GPIO_InitStruct);
1096 
1097   /* OctoSPI D0 GPIO pin configuration  */
1098   GPIO_InitStruct.Pin       = OSPI_NOR_D0_PIN;
1099   GPIO_InitStruct.Alternate = OSPI_NOR_D0_PIN_AF;
1100   HAL_GPIO_Init(OSPI_NOR_D0_GPIO_PORT, &GPIO_InitStruct);
1101 
1102   /* OctoSPI D1 GPIO pin configuration  */
1103   GPIO_InitStruct.Pin       = OSPI_NOR_D1_PIN;
1104   GPIO_InitStruct.Alternate = OSPI_NOR_D1_PIN_AF;
1105   HAL_GPIO_Init(OSPI_NOR_D1_GPIO_PORT, &GPIO_InitStruct);
1106 
1107   /* OctoSPI D2 GPIO pin configuration  */
1108   GPIO_InitStruct.Pin       = OSPI_NOR_D2_PIN;
1109   GPIO_InitStruct.Alternate = OSPI_NOR_D2_PIN_AF;
1110   HAL_GPIO_Init(OSPI_NOR_D2_GPIO_PORT, &GPIO_InitStruct);
1111 
1112   /* OctoSPI D3 GPIO pin configuration  */
1113   GPIO_InitStruct.Pin       = OSPI_NOR_D3_PIN;
1114   GPIO_InitStruct.Alternate = OSPI_NOR_D3_PIN_AF;
1115   HAL_GPIO_Init(OSPI_NOR_D3_GPIO_PORT, &GPIO_InitStruct);
1116 
1117   /* OctoSPI D4 GPIO pin configuration  */
1118   GPIO_InitStruct.Pin       = OSPI_NOR_D4_PIN;
1119   GPIO_InitStruct.Alternate = OSPI_NOR_D4_PIN_AF;
1120   HAL_GPIO_Init(OSPI_NOR_D4_GPIO_PORT, &GPIO_InitStruct);
1121 
1122   /* OctoSPI D5 GPIO pin configuration  */
1123   GPIO_InitStruct.Pin       = OSPI_NOR_D5_PIN;
1124   GPIO_InitStruct.Alternate = OSPI_NOR_D5_PIN_AF;
1125   HAL_GPIO_Init(OSPI_NOR_D5_GPIO_PORT, &GPIO_InitStruct);
1126 
1127   /* OctoSPI D6 GPIO pin configuration  */
1128   GPIO_InitStruct.Pin       = OSPI_NOR_D6_PIN;
1129   GPIO_InitStruct.Alternate = OSPI_NOR_D6_PIN_AF;
1130   HAL_GPIO_Init(OSPI_NOR_D6_GPIO_PORT, &GPIO_InitStruct);
1131 
1132   /* OctoSPI D7 GPIO pin configuration  */
1133   GPIO_InitStruct.Pin       = OSPI_NOR_D7_PIN;
1134   GPIO_InitStruct.Alternate = OSPI_NOR_D7_PIN_AF;
1135   HAL_GPIO_Init(OSPI_NOR_D7_GPIO_PORT, &GPIO_InitStruct);
1136 }
1137 
1138 /**
1139   * @brief  De-Initializes the OSPI MSP.
1140   * @param  hospi OSPI handle
1141   * @retval None
1142   */
OSPI_NOR_MspDeInit(OSPI_HandleTypeDef * hospi)1143 static void OSPI_NOR_MspDeInit(OSPI_HandleTypeDef *hospi)
1144 {
1145   /* hospi unused argument(s) compilation warning */
1146   UNUSED(hospi);
1147 
1148   /* OctoSPI GPIO pins de-configuration  */
1149   HAL_GPIO_DeInit(OSPI_NOR_CLK_GPIO_PORT, OSPI_NOR_CLK_PIN);
1150   HAL_GPIO_DeInit(OSPI_NOR_DQS_GPIO_PORT, OSPI_NOR_DQS_PIN);
1151   HAL_GPIO_DeInit(OSPI_NOR_CS_GPIO_PORT, OSPI_NOR_CS_PIN);
1152   HAL_GPIO_DeInit(OSPI_NOR_D0_GPIO_PORT, OSPI_NOR_D0_PIN);
1153   HAL_GPIO_DeInit(OSPI_NOR_D1_GPIO_PORT, OSPI_NOR_D1_PIN);
1154   HAL_GPIO_DeInit(OSPI_NOR_D2_GPIO_PORT, OSPI_NOR_D2_PIN);
1155   HAL_GPIO_DeInit(OSPI_NOR_D3_GPIO_PORT, OSPI_NOR_D3_PIN);
1156   HAL_GPIO_DeInit(OSPI_NOR_D4_GPIO_PORT, OSPI_NOR_D4_PIN);
1157   HAL_GPIO_DeInit(OSPI_NOR_D5_GPIO_PORT, OSPI_NOR_D5_PIN);
1158   HAL_GPIO_DeInit(OSPI_NOR_D6_GPIO_PORT, OSPI_NOR_D6_PIN);
1159   HAL_GPIO_DeInit(OSPI_NOR_D7_GPIO_PORT, OSPI_NOR_D7_PIN);
1160 
1161   /* Reset the OctoSPI memory interface */
1162   OSPI_NOR_FORCE_RESET();
1163   OSPI_NOR_RELEASE_RESET();
1164 
1165   /* Disable the OctoSPI memory interface clock */
1166   OSPI_NOR_CLK_DISABLE();
1167 }
1168 
1169 /**
1170   * @brief  This function reset the OSPI memory.
1171   * @param  Instance  OSPI instance
1172   * @retval BSP status
1173   */
OSPI_NOR_ResetMemory(uint32_t Instance)1174 static int32_t OSPI_NOR_ResetMemory(uint32_t Instance)
1175 {
1176   int32_t ret = BSP_ERROR_NONE;
1177 
1178   /* Check if the instance is supported */
1179   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
1180   {
1181     ret = BSP_ERROR_WRONG_PARAM;
1182   }
1183   else if (MX25LM51245G_ResetEnable(&hospi_nor[Instance], BSP_OSPI_NOR_SPI_MODE,
1184                                     BSP_OSPI_NOR_STR_TRANSFER) != MX25LM51245G_OK)
1185   {
1186     ret = BSP_ERROR_COMPONENT_FAILURE;
1187   }
1188   else if (MX25LM51245G_ResetMemory(&hospi_nor[Instance], BSP_OSPI_NOR_SPI_MODE,
1189                                     BSP_OSPI_NOR_STR_TRANSFER) != MX25LM51245G_OK)
1190   {
1191     ret = BSP_ERROR_COMPONENT_FAILURE;
1192   }
1193   else if (MX25LM51245G_ResetEnable(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE,
1194                                     BSP_OSPI_NOR_STR_TRANSFER) != MX25LM51245G_OK)
1195   {
1196     ret = BSP_ERROR_COMPONENT_FAILURE;
1197   }
1198   else if (MX25LM51245G_ResetMemory(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE,
1199                                     BSP_OSPI_NOR_STR_TRANSFER) != MX25LM51245G_OK)
1200   {
1201     ret = BSP_ERROR_COMPONENT_FAILURE;
1202   }
1203   else if (MX25LM51245G_ResetEnable(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE,
1204                                     BSP_OSPI_NOR_DTR_TRANSFER) != MX25LM51245G_OK)
1205   {
1206     ret = BSP_ERROR_COMPONENT_FAILURE;
1207   }
1208   else if (MX25LM51245G_ResetMemory(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE,
1209                                     BSP_OSPI_NOR_DTR_TRANSFER) != MX25LM51245G_OK)
1210   {
1211     ret = BSP_ERROR_COMPONENT_FAILURE;
1212   }
1213   else
1214   {
1215     Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_INDIRECT;     /* After reset S/W setting to indirect access  */
1216     Ospi_Nor_Ctx[Instance].InterfaceMode = BSP_OSPI_NOR_SPI_MODE;    /* After reset H/W back to SPI mode by default */
1217     Ospi_Nor_Ctx[Instance].TransferRate  = BSP_OSPI_NOR_STR_TRANSFER; /* After reset S/W setting to STR mode        */
1218 
1219     /* After SWreset CMD, wait in case SWReset occurred during erase operation */
1220     HAL_Delay(MX25LM51245G_RESET_MAX_TIME);
1221   }
1222 
1223   /* Return BSP status */
1224   return ret;
1225 }
1226 
1227 /**
1228   * @brief  This function enables the octal DTR mode of the memory.
1229   * @param  Instance  OSPI instance
1230   * @retval BSP status
1231   */
OSPI_NOR_EnterDOPIMode(uint32_t Instance)1232 static int32_t OSPI_NOR_EnterDOPIMode(uint32_t Instance)
1233 {
1234   int32_t ret;
1235   uint8_t reg[2];
1236 
1237   /* Check if the instance is supported */
1238   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
1239   {
1240     ret = BSP_ERROR_WRONG_PARAM;
1241   }
1242   /* Enable write operations */
1243   else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1244                                     Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
1245   {
1246     ret = BSP_ERROR_COMPONENT_FAILURE;
1247   }
1248   /* Write Configuration register 2 (with new dummy cycles) */
1249   else if (MX25LM51245G_WriteCfg2Register(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1250                                           Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_CR2_REG3_ADDR,
1251                                           MX25LM51245G_CR2_DC_6_CYCLES) != MX25LM51245G_OK)
1252   {
1253     ret = BSP_ERROR_COMPONENT_FAILURE;
1254   }
1255   /* Enable write operations */
1256   else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1257                                     Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
1258   {
1259     ret = BSP_ERROR_COMPONENT_FAILURE;
1260   }
1261   /* Write Configuration register 2 (with Octal I/O SPI protocol) */
1262   else if (MX25LM51245G_WriteCfg2Register(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1263                                           Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_CR2_REG1_ADDR,
1264                                           MX25LM51245G_CR2_DOPI) != MX25LM51245G_OK)
1265   {
1266     ret = BSP_ERROR_COMPONENT_FAILURE;
1267   }
1268   else
1269   {
1270     /* Wait that the configuration is effective and check that memory is ready */
1271     HAL_Delay(MX25LM51245G_WRITE_REG_MAX_TIME);
1272 
1273     /* Reconfigure the memory type of the peripheral */
1274     hospi_nor[Instance].Init.MemoryType            = HAL_OSPI_MEMTYPE_MACRONIX;
1275     hospi_nor[Instance].Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
1276     if (HAL_OSPI_Init(&hospi_nor[Instance]) != HAL_OK)
1277     {
1278       ret = BSP_ERROR_PERIPH_FAILURE;
1279     }
1280     /* Check Flash busy ? */
1281     else if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE,
1282                                               BSP_OSPI_NOR_DTR_TRANSFER) != MX25LM51245G_OK)
1283     {
1284       ret = BSP_ERROR_COMPONENT_FAILURE;
1285     }
1286     /* Check the configuration has been correctly done */
1287     else if (MX25LM51245G_ReadCfg2Register(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE, BSP_OSPI_NOR_DTR_TRANSFER,
1288                                            MX25LM51245G_CR2_REG1_ADDR, reg) != MX25LM51245G_OK)
1289     {
1290       ret = BSP_ERROR_COMPONENT_FAILURE;
1291     }
1292     else if (reg[0] != MX25LM51245G_CR2_DOPI)
1293     {
1294       ret = BSP_ERROR_COMPONENT_FAILURE;
1295     }
1296     else
1297     {
1298       ret = BSP_ERROR_NONE;
1299     }
1300   }
1301 
1302   /* Return BSP status */
1303   return ret;
1304 }
1305 
1306 /**
1307   * @brief  This function enables the octal STR mode of the memory.
1308   * @param  Instance  OSPI instance
1309   * @retval BSP status
1310   */
OSPI_NOR_EnterSOPIMode(uint32_t Instance)1311 static int32_t OSPI_NOR_EnterSOPIMode(uint32_t Instance)
1312 {
1313   int32_t ret;
1314   uint8_t reg[2];
1315 
1316   /* Check if the instance is supported */
1317   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
1318   {
1319     ret = BSP_ERROR_WRONG_PARAM;
1320   }
1321   /* Enable write operations */
1322   else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1323                                     Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
1324   {
1325     ret = BSP_ERROR_COMPONENT_FAILURE;
1326   }
1327   /* Write Configuration register 2 (with new dummy cycles) */
1328   else if (MX25LM51245G_WriteCfg2Register(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1329                                           Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_CR2_REG3_ADDR,
1330                                           MX25LM51245G_CR2_DC_6_CYCLES) != MX25LM51245G_OK)
1331   {
1332     ret = BSP_ERROR_COMPONENT_FAILURE;
1333   }
1334   /* Enable write operations */
1335   else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1336                                     Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
1337   {
1338     ret = BSP_ERROR_COMPONENT_FAILURE;
1339   }
1340   /* Write Configuration register 2 (with Octal I/O SPI protocol) */
1341   else if (MX25LM51245G_WriteCfg2Register(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1342                                           Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_CR2_REG1_ADDR,
1343                                           MX25LM51245G_CR2_SOPI) != MX25LM51245G_OK)
1344   {
1345     ret = BSP_ERROR_COMPONENT_FAILURE;
1346   }
1347   else
1348   {
1349     /* Wait that the configuration is effective and check that memory is ready */
1350     HAL_Delay(MX25LM51245G_WRITE_REG_MAX_TIME);
1351 
1352     /* Check Flash busy ? */
1353     if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE,
1354                                          BSP_OSPI_NOR_STR_TRANSFER) != MX25LM51245G_OK)
1355     {
1356       ret = BSP_ERROR_COMPONENT_FAILURE;
1357     }
1358     /* Check the configuration has been correctly done */
1359     else if (MX25LM51245G_ReadCfg2Register(&hospi_nor[Instance], BSP_OSPI_NOR_OPI_MODE, BSP_OSPI_NOR_STR_TRANSFER,
1360                                            MX25LM51245G_CR2_REG1_ADDR, reg) != MX25LM51245G_OK)
1361     {
1362       ret = BSP_ERROR_COMPONENT_FAILURE;
1363     }
1364     else if (reg[0] != MX25LM51245G_CR2_SOPI)
1365     {
1366       ret = BSP_ERROR_COMPONENT_FAILURE;
1367     }
1368     else
1369     {
1370       ret = BSP_ERROR_NONE;
1371     }
1372   }
1373 
1374   /* Return BSP status */
1375   return ret;
1376 }
1377 
1378 /**
1379   * @brief  This function disables the octal DTR or STR mode of the memory.
1380   * @param  Instance  OSPI instance
1381   * @retval BSP status
1382   */
OSPI_NOR_ExitOPIMode(uint32_t Instance)1383 static int32_t OSPI_NOR_ExitOPIMode(uint32_t Instance)
1384 {
1385   int32_t ret = BSP_ERROR_NONE;
1386   uint8_t reg[2];
1387 
1388   /* Check if the instance is supported */
1389   if (Instance >= OSPI_NOR_INSTANCES_NUMBER)
1390   {
1391     ret = BSP_ERROR_WRONG_PARAM;
1392   }
1393   /* Enable write operations */
1394   else if (MX25LM51245G_WriteEnable(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1395                                     Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)
1396   {
1397     ret = BSP_ERROR_COMPONENT_FAILURE;
1398   }
1399   else
1400   {
1401     /* Write Configuration register 2 (with SPI protocol) */
1402     reg[0] = 0;
1403     reg[1] = 0;
1404     if (MX25LM51245G_WriteCfg2Register(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode,
1405                                        Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_CR2_REG1_ADDR,
1406                                        reg[0]) != MX25LM51245G_OK)
1407     {
1408       ret = BSP_ERROR_COMPONENT_FAILURE;
1409     }
1410     else
1411     {
1412       /* Wait that the configuration is effective and check that memory is ready */
1413       HAL_Delay(MX25LM51245G_WRITE_REG_MAX_TIME);
1414 
1415       if (Ospi_Nor_Ctx[Instance].TransferRate == BSP_OSPI_NOR_DTR_TRANSFER)
1416       {
1417         /* Reconfigure the memory type of the peripheral */
1418         hospi_nor[Instance].Init.MemoryType            = HAL_OSPI_MEMTYPE_MICRON;
1419         hospi_nor[Instance].Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
1420         if (HAL_OSPI_Init(&hospi_nor[Instance]) != HAL_OK)
1421         {
1422           ret = BSP_ERROR_PERIPH_FAILURE;
1423         }
1424       }
1425 
1426       if (ret == BSP_ERROR_NONE)
1427       {
1428         /* Check Flash busy ? */
1429         if (MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], BSP_OSPI_NOR_SPI_MODE,
1430                                              BSP_OSPI_NOR_STR_TRANSFER) != MX25LM51245G_OK)
1431         {
1432           ret = BSP_ERROR_COMPONENT_FAILURE;
1433         }
1434         /* Check the configuration has been correctly done */
1435         else if (MX25LM51245G_ReadCfg2Register(&hospi_nor[Instance], BSP_OSPI_NOR_SPI_MODE, BSP_OSPI_NOR_STR_TRANSFER,
1436                                                MX25LM51245G_CR2_REG1_ADDR, reg) != MX25LM51245G_OK)
1437         {
1438           ret = BSP_ERROR_COMPONENT_FAILURE;
1439         }
1440         else if (reg[0] != 0U)
1441         {
1442           ret = BSP_ERROR_COMPONENT_FAILURE;
1443         }
1444         else
1445         {
1446           /* Nothing to do */
1447         }
1448       }
1449     }
1450   }
1451 
1452   /* Return BSP status */
1453   return ret;
1454 }
1455 
1456 /**
1457   * @brief  This function enables delay block.
1458   * @param  ospi_Instance  OSPI instance
1459   * @retval BSP status
1460   */
OSPI_DLYB_Enable(OSPI_HandleTypeDef * hospi)1461 static int32_t OSPI_DLYB_Enable(OSPI_HandleTypeDef *hospi)
1462 {
1463   LL_DLYB_CfgTypeDef dlyb_cfg, dlyb_cfg_test;
1464   int32_t ret = BSP_ERROR_NONE;
1465   uint32_t div_value = 4;
1466 
1467   /* Delay block configuration ------------------------------------------------ */
1468   if (HAL_OSPI_DLYB_GetClockPeriod(hospi, &dlyb_cfg) != HAL_OK)
1469   {
1470     ret = BSP_ERROR_PERIPH_FAILURE;
1471   }
1472 
1473   /* PhaseSel is divided by 4 (emperic value)*/
1474   dlyb_cfg.PhaseSel /= div_value;
1475 
1476   /* save the present configuration for check*/
1477   dlyb_cfg_test = dlyb_cfg;
1478 
1479   /*set delay block configuration*/
1480   if (HAL_OSPI_DLYB_SetConfig(hospi, &dlyb_cfg) != HAL_OK)
1481   {
1482     ret = BSP_ERROR_PERIPH_FAILURE;
1483   }
1484 
1485   /*check the set value*/
1486   if (HAL_OSPI_DLYB_GetConfig(hospi, &dlyb_cfg) != HAL_OK)
1487   {
1488     ret = BSP_ERROR_PERIPH_FAILURE;
1489   }
1490 
1491   if ((dlyb_cfg.PhaseSel != dlyb_cfg_test.PhaseSel) || (dlyb_cfg.Units != dlyb_cfg_test.Units))
1492   {
1493     ret = BSP_ERROR_PERIPH_FAILURE;
1494   }
1495 
1496   /* Return BSP status */
1497   return ret;
1498 }
1499 
1500 /**
1501   * @}
1502   */
1503 
1504 
1505 
1506 /**
1507   * @}
1508   */
1509 
1510 /**
1511   * @}
1512   */
1513 
1514 /**
1515   * @}
1516   */
1517 
1518 /**
1519   * @}
1520   */
1521 
1522