1 /**
2   ******************************************************************************
3   * @file    stm32mp1xx_ll_utils.c
4   * @author  MCD Application Team
5   * @brief   UTILS LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * Copyright (c) 2019 STMicroelectronics.
10   * All rights reserved.
11   *
12   * This software is licensed under terms that can be found in the LICENSE file
13   * in the root directory of this software component.
14   * If no LICENSE file comes with this software, it is provided AS-IS.
15   *
16   ******************************************************************************
17   */
18 /* Includes ------------------------------------------------------------------*/
19 #include "stm32mp1xx_ll_utils.h"
20 #include "stm32mp1xx_ll_system.h"
21 #include "stm32mp1xx_ll_bus.h"
22 #include "stm32mp1xx_ll_rcc.h"
23 
24 #ifdef  USE_FULL_ASSERT
25 #include "stm32_assert.h"
26 #else
27 #define assert_param(expr) ((void)0U)
28 #endif /* USE_FULL_ASSERT */
29 
30 /** @addtogroup STM32MP1xx_LL_Driver
31   * @{
32   */
33 
34 /** @addtogroup UTILS_LL
35   * @{
36   */
37 
38 /* Private types -------------------------------------------------------------*/
39 /* Private variables ---------------------------------------------------------*/
40 /* Private constants ---------------------------------------------------------*/
41 /** @addtogroup UTILS_LL_Private_Constants
42   * @{
43   */
44 
45 /* Defines used for PLL type */
46 #define UTILS_PLL_1600_TYPE       00000000U
47 #define UTILS_PLL_800_TYPE        00000001U
48 
49 /* Defines used for PLL range */
50 #define UTILS_PLL1600_INPUT_MIN    8000000U /*!< Frequency min for PLL1600 type input, in Hz */
51 #define UTILS_PLL1600_INPUT_MAX   16000000U /*!< Frequency max for PLL1600 type input, in Hz */
52 #define UTILS_PLL800_INPUT_MIN     4000000U /*!< Frequency min for PLL800 type input, in Hz */
53 #define UTILS_PLL800_INPUT_MED     8000000U /*!< Frequency medium range for PLL800 type input, in Hz */
54 #define UTILS_PLL800_INPUT_MAX    16000000U /*!< Frequency max for PLL800 type input, in Hz */
55 
56 #define UTILS_PLL1600_OUTPUT_MIN    800000000U /*!< Frequency min for PLL1600 type output, in Hz */
57 #define UTILS_PLL1600_OUTPUT_MAX   1600000000U /*!< Frequency max for PLL1600 type output, in Hz */
58 #define UTILS_PLL800_OUTPUT_MIN     400000000U /*!< Frequency min for PLL800 type output, in Hz */
59 #define UTILS_PLL800_OUTPUT_MAX     800000000U /*!< Frequency max for PLL800 type output, in Hz */
60 
61 /* Defines used for HSE range */
62 #define UTILS_HSE_FREQUENCY_MIN      8000000U        /*!< Frequency min for HSE frequency, in Hz   */
63 #define UTILS_HSE_FREQUENCY_MAX     48000000U        /*!< Frequency max for HSE frequency, in Hz   */
64 
65 /**
66   * @}
67   */
68 
69 /* Private macros ------------------------------------------------------------*/
70 /** @addtogroup UTILS_LL_Private_Macros
71   * @{
72   */
73 #define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \
74                                       || ((__VALUE__) == LL_RCC_APB1_DIV_2) \
75                                       || ((__VALUE__) == LL_RCC_APB1_DIV_4) \
76                                       || ((__VALUE__) == LL_RCC_APB1_DIV_8) \
77                                       || ((__VALUE__) == LL_RCC_APB1_DIV_16))
78 
79 #define IS_LL_UTILS_APB2_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB2_DIV_1) \
80                                       || ((__VALUE__) == LL_RCC_APB2_DIV_2) \
81                                       || ((__VALUE__) == LL_RCC_APB2_DIV_4) \
82                                       || ((__VALUE__) == LL_RCC_APB2_DIV_8) \
83                                       || ((__VALUE__) == LL_RCC_APB2_DIV_16))
84 
85 #define IS_LL_UTILS_APB3_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB3_DIV_1) \
86                                       || ((__VALUE__) == LL_RCC_APB3_DIV_2) \
87                                       || ((__VALUE__) == LL_RCC_APB3_DIV_4) \
88                                       || ((__VALUE__) == LL_RCC_APB3_DIV_8) \
89                                       || ((__VALUE__) == LL_RCC_APB3_DIV_16))
90 
91 #define IS_LL_UTILS_APB4_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB4_DIV_1) \
92                                       || ((__VALUE__) == LL_RCC_APB4_DIV_2) \
93                                       || ((__VALUE__) == LL_RCC_APB4_DIV_4) \
94                                       || ((__VALUE__) == LL_RCC_APB4_DIV_8) \
95                                       || ((__VALUE__) == LL_RCC_APB4_DIV_16))
96 
97 #define IS_LL_UTILS_APB5_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB5_DIV_1) \
98                                       || ((__VALUE__) == LL_RCC_APB5_DIV_2) \
99                                       || ((__VALUE__) == LL_RCC_APB5_DIV_4) \
100                                       || ((__VALUE__) == LL_RCC_APB5_DIV_8) \
101                                       || ((__VALUE__) == LL_RCC_APB5_DIV_16))
102 
103 #define IS_LL_UTILS_PLLM_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 64U))
104 
105 #define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((4U <= (__VALUE__)) && ((__VALUE__) <= 512U))
106 
107 #define IS_LL_UTILS_PLLP_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 128U))
108 
109 #define IS_LL_UTILS_FRACV_VALUE(__VALUE__) ((__VALUE__) <= 0x1FFFU)
110 
111 #define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__, __TYPE__)  ( \
112 (((__TYPE__) == UTILS_PLL_1600_TYPE) && (UTILS_PLL1600_INPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLL1600_INPUT_MAX)) || \
113 (((__TYPE__) == UTILS_PLL_800_TYPE) && (UTILS_PLL800_INPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLL800_INPUT_MAX)))
114 
115 #define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__, __TYPE__) ( \
116 (((__TYPE__) == UTILS_PLL_1600_TYPE) && (UTILS_PLL1600_OUTPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLL1600_OUTPUT_MAX)) || \
117 (((__TYPE__) == UTILS_PLL_800_TYPE) && (UTILS_PLL800_OUTPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLL800_OUTPUT_MAX)))
118 
119 #define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) || \
120                                            ((__STATE__) == LL_UTILS_HSEBYPASSDIG_ON) || \
121                                            ((__STATE__) == LL_UTILS_HSEBYPASS_OFF))
122 
123 #define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= UTILS_HSE_FREQUENCY_MIN) && ((__FREQUENCY__) <= UTILS_HSE_FREQUENCY_MAX))
124 /**
125   * @}
126   */
127 /* Private function prototypes -----------------------------------------------*/
128 /** @defgroup UTILS_LL_Private_Functions UTILS Private functions
129   * @{
130   */
131 static void UTILS_CheckPLLParameters(LL_UTILS_PLLTypeDef *UTILS_PLLStruct);
132 static uint32_t    UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLTypeDef *UTILS_PLLStruct);
133 static void UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
134 static ErrorStatus UTILS_IsPLLsReady(void);
135 /**
136   * @}
137   */
138 
139 /* Exported functions --------------------------------------------------------*/
140 /** @addtogroup UTILS_LL_Exported_Functions
141   * @{
142   */
143 
144 /** @addtogroup UTILS_LL_EF_DELAY
145   * @{
146   */
147 #if defined(CORE_CM4)
148 /**
149   * @brief  This function configures the Cortex-M SysTick source to have 1ms time base.
150   * @note   When a RTOS is used, it is recommended to avoid changing the Systick
151   *         configuration by calling this function, for a delay use rather osDelay RTOS service.
152   * @param  CPU_Frequency Core frequency in Hz
153   * @note   CPU_Frequency can be calculated thanks to RCC helper macro or function
154   *         @ref LL_RCC_GetSystemClocksFreq
155   *         - Use  MCU_Frequency structure element returned by function above
156   * @retval None
157   */
LL_Init1msTick(uint32_t CPU_Frequency)158 void LL_Init1msTick(uint32_t CPU_Frequency)
159 {
160   /* Use frequency provided in argument */
161   LL_InitTick(CPU_Frequency, 1000U);
162 }
163 
164 /**
165   * @brief  This function provides accurate delay (in milliseconds) based
166   *         on SysTick counter flag for Cortex-M processor
167   * @note   When a RTOS is used, it is recommended to avoid using blocking delay
168   *         and use rather osDelay service.
169   * @note   To respect 1ms timebase, user should call @ref LL_Init1msTick function which
170   *         will configure Systick to 1ms
171   * @param  Delay specifies the delay time length, in milliseconds.
172   * @retval None
173   */
LL_mDelay(uint32_t Delay)174 void LL_mDelay(uint32_t Delay)
175 {
176   uint32_t count = Delay;
177   __IO uint32_t  tmp = SysTick->CTRL;  /* Clear the COUNTFLAG first */
178   /* Add this code to indicate that local variable is not used */
179   ((void)tmp);
180 
181   /* Add a period to guaranty minimum wait */
182   if (count < LL_MAX_DELAY)
183   {
184     count++;
185   }
186 
187   while (count != 0U)
188   {
189     if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
190     {
191       count--;
192     }
193   }
194 }
195 #endif /* CORE_CM4 */
196 /**
197   * @}
198   */
199 
200 /** @addtogroup UTILS_EF_SYSTEM
201   *  @brief    System Configuration functions
202   *
203   @verbatim
204  ===============================================================================
205            ##### System Configuration functions #####
206  ===============================================================================
207     [..]
208          MPUSS core (CA7), MCU core (CM4), ACLK, HCLK and APB buses clocks
209          configuration
210 
211          (+) The maximum frequency of the SystemCoreClock MPUSS (CA7) is 800 MHz
212          (+) The maximum frequency of the ACLK (plus HCLK5 and HCLK6) is 266 MHz.
213          (+) The maximum frequency of the SystemCoreClock MCU (CM4) is 209 MHz
214          (+) The maximum frequency of the PCLK1, PCLK2 and PCLK3 is 104.5 MHz.
215          (+) The maximum frequency of the PCLK4 and PCLK5 is 133 MHz.
216   @endverbatim
217   * @{
218   */
219 /**
220   * @brief  This function sets directly SystemCoreClock CMSIS variable.
221   * @note   Variable can be calculated also through SystemCoreClockUpdate function.
222   * @param  CPU_Frequency Core frequency in Hz
223   * @note   CPU_Frequency can be calculated thanks to RCC helper macro or function
224   *         @ref LL_RCC_GetSystemClocksFreq
225   *         - When code runs on CM4 core, use  MCU_Frequency structure element
226   *           returned by function above
227   *         - When code runs on CA7 core, use  MPUSS_Frequency structure element
228   *           returned by function above
229   * @retval None
230   */
LL_SetSystemCoreClock(uint32_t CPU_Frequency)231 void LL_SetSystemCoreClock(uint32_t CPU_Frequency)
232 {
233   /* System core clock  frequency */
234   SystemCoreClock = CPU_Frequency;
235 }
236 
237 /**
238   * @brief  This function configures system clocks with HSE as clock source of the PLLs
239   * @note   The application need to ensure that PLLs are disabled.
240   * @note   Function is based on the following formula where x = {1,2,3,4} and Y = {P,Q,R}:
241   *         - PLLxY output frequency = (((HSE frequency / PLLxM) * (PLLxN + (FRACV / 8192))) / PLLxY)
242   *         - PLLxM: ensure that the VCO input frequency ranges from 8 to 16 MHz
243   *           for PLL1600 type and from 4 to 16 MHz for PLL_800 type
244   *           (PLLxVCO_input = HSE frequency / PLLxM)
245   *         - PLLxN: ensure that the VCO output frequency is between 800 and 1600
246   *           MHz for PLL_1600 type and between 400 and 800 MHz for PLL_800 type
247   *           (PLLxVCO_output = PLLVCO_input * (PLLxN + (FRACV / 8192)))
248   *         - PLLxP: ensure that max frequency is reached (PLLxVCO_output / PLLxP)
249   *             - PLL1P output max frequency is 800000000 Hz
250   *             - PLL2P output max frequency is 266000000 Hz
251   *             - PLL2Q output max frequency is 533000000 Hz
252   *             - PLL2R output max frequency is 533000000 Hz
253   *             - PLL3P output max frequency is 209000000 Hz
254   * @param  HSEFrequency Value between 8000000 Hz and 48000000 Hz
255   * @param  HSEBypass This parameter can be one of the following values:
256   *         @arg @ref LL_UTILS_HSEBYPASS_ON
257   *         @arg @ref LL_UTILS_HSEBYPASSDIG_ON
258   *         @arg @ref LL_UTILS_HSEBYPASS_OFF
259   * @param  UTILS_PLLsInitStruct pointer to a @ref LL_UTILS_PLLsInitTypeDef structure that contains
260   *                             the configuration information for the PLL.
261   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
262   *                             the configuration information for the BUS prescalers.
263   * @retval An ErrorStatus enumeration value:
264   *          - SUCCESS: Max frequency configuration done
265   *          - ERROR: Max frequency configuration not done
266   */
LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency,uint32_t HSEBypass,LL_UTILS_PLLsInitTypeDef * UTILS_PLLsInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)267 ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass,
268                                          LL_UTILS_PLLsInitTypeDef *UTILS_PLLsInitStruct,
269                                          LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
270 {
271   ErrorStatus status = SUCCESS;
272   uint32_t pllfreq;
273   uint32_t vcoinput_freqPLL3, vcoinput_freqPLL4;
274 #ifdef  USE_FULL_ASSERT
275   uint32_t vcoinput_freq, vcooutput_freq;
276 #endif
277 
278   /* Check the parameters */
279   UTILS_CheckPLLParameters(&UTILS_PLLsInitStruct->PLL1);
280   UTILS_CheckPLLParameters(&UTILS_PLLsInitStruct->PLL2);
281   UTILS_CheckPLLParameters(&UTILS_PLLsInitStruct->PLL3);
282   UTILS_CheckPLLParameters(&UTILS_PLLsInitStruct->PLL4);
283   assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency));
284   assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
285 
286   vcoinput_freqPLL3 = HSEFrequency / UTILS_PLLsInitStruct->PLL3.PLLM;
287   vcoinput_freqPLL4 = HSEFrequency / UTILS_PLLsInitStruct->PLL4.PLLM;
288 
289 #ifdef  USE_FULL_ASSERT
290   /* Check VCO Input frequency */
291   vcoinput_freq = HSEFrequency / UTILS_PLLsInitStruct->PLL1.PLLM;
292   assert_param(IS_LL_UTILS_PLLVCO_INPUT(vcoinput_freq, UTILS_PLL_1600_TYPE));
293 
294   vcoinput_freq = HSEFrequency / UTILS_PLLsInitStruct->PLL2.PLLM;
295   assert_param(IS_LL_UTILS_PLLVCO_INPUT(vcoinput_freq, UTILS_PLL_1600_TYPE));
296 
297   assert_param(IS_LL_UTILS_PLLVCO_INPUT(vcoinput_freqPLL3, UTILS_PLL_800_TYPE));
298   assert_param(IS_LL_UTILS_PLLVCO_INPUT(vcoinput_freqPLL4, UTILS_PLL_800_TYPE));
299 
300   /* Check VCO Output frequency */
301   vcooutput_freq = (LL_RCC_CalcPLLClockFreq(
302                       HSEFrequency,
303                       UTILS_PLLsInitStruct->PLL1.PLLM,
304                       UTILS_PLLsInitStruct->PLL1.PLLN,
305                       UTILS_PLLsInitStruct->PLL1.PLLFRACV,
306                       1U) * 2U);
307   assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(vcooutput_freq, UTILS_PLL_1600_TYPE));
308 
309   vcooutput_freq = (LL_RCC_CalcPLLClockFreq(
310                       HSEFrequency,
311                       UTILS_PLLsInitStruct->PLL2.PLLM,
312                       UTILS_PLLsInitStruct->PLL2.PLLN,
313                       UTILS_PLLsInitStruct->PLL2.PLLFRACV,
314                       1U) * 2U);
315   assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(vcooutput_freq, UTILS_PLL_1600_TYPE));
316 
317   vcooutput_freq = LL_RCC_CalcPLLClockFreq(
318                      HSEFrequency,
319                      UTILS_PLLsInitStruct->PLL3.PLLM,
320                      UTILS_PLLsInitStruct->PLL3.PLLN,
321                      UTILS_PLLsInitStruct->PLL3.PLLFRACV,
322                      1U);
323   assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(vcooutput_freq, UTILS_PLL_800_TYPE));
324 
325   vcooutput_freq = LL_RCC_CalcPLLClockFreq(
326                      HSEFrequency,
327                      UTILS_PLLsInitStruct->PLL4.PLLM,
328                      UTILS_PLLsInitStruct->PLL4.PLLN,
329                      UTILS_PLLsInitStruct->PLL4.PLLFRACV,
330                      1U);
331   assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(vcooutput_freq, UTILS_PLL_800_TYPE));
332 #endif /* USE_FULL_ASSERT */
333 
334   /* Check if one of the PLL is enabled */
335   if (UTILS_IsPLLsReady() == SUCCESS)
336   {
337     /* Check if need to enable HSE bypass feature or not */
338     if (HSEBypass == LL_UTILS_HSEBYPASS_ON)
339     {
340       LL_RCC_HSE_EnableBypass();
341     }
342     else if (HSEBypass == LL_UTILS_HSEBYPASSDIG_ON)
343     {
344       LL_RCC_HSE_EnableDigBypass();
345     }
346     else
347     {
348       /* Clear HSE BYPASS and HSE BYPASS DIGITAL bits */
349       LL_RCC_HSE_DisableDigBypass();
350     }
351 
352     /* Enable HSE if not enabled */
353     if (LL_RCC_HSE_IsReady() != 1U)
354     {
355       LL_RCC_HSE_Enable();
356       while (LL_RCC_HSE_IsReady() != 1U)
357       {
358         /* Wait for HSE ready */
359       }
360     }
361 
362     /* Configure PLL1 */
363     LL_RCC_PLL12_SetSource(LL_RCC_PLL12SOURCE_HSE);
364 
365     LL_RCC_PLL1_SetM(UTILS_PLLsInitStruct->PLL1.PLLM);
366     LL_RCC_PLL1_SetN(UTILS_PLLsInitStruct->PLL1.PLLN);
367     LL_RCC_PLL1_SetP(UTILS_PLLsInitStruct->PLL1.PLLP);
368 
369     LL_RCC_PLL1FRACV_Disable();
370     LL_RCC_PLL1_SetFRACV(UTILS_PLLsInitStruct->PLL1.PLLFRACV);
371     LL_RCC_PLL1FRACV_Enable();
372 
373     LL_RCC_PLL1CSG_Disable();
374 
375     /* Configure PLL2 */
376     LL_RCC_PLL2_SetM(UTILS_PLLsInitStruct->PLL2.PLLM);
377     LL_RCC_PLL2_SetN(UTILS_PLLsInitStruct->PLL2.PLLN);
378     LL_RCC_PLL2_SetP(UTILS_PLLsInitStruct->PLL2.PLLP);
379     LL_RCC_PLL2_SetQ(UTILS_PLLsInitStruct->PLL2.PLLQ);
380     LL_RCC_PLL2_SetR(UTILS_PLLsInitStruct->PLL2.PLLR);
381 
382     LL_RCC_PLL2FRACV_Disable();
383     LL_RCC_PLL2_SetFRACV(UTILS_PLLsInitStruct->PLL2.PLLFRACV);
384     LL_RCC_PLL2FRACV_Enable();
385 
386     LL_RCC_PLL2CSG_Disable();
387 
388     /* Configure PLL3 */
389     LL_RCC_PLL3_SetSource(LL_RCC_PLL3SOURCE_HSE);
390 
391     LL_RCC_PLL3_SetM(UTILS_PLLsInitStruct->PLL3.PLLM);
392     LL_RCC_PLL3_SetN(UTILS_PLLsInitStruct->PLL3.PLLN);
393     LL_RCC_PLL3_SetP(UTILS_PLLsInitStruct->PLL3.PLLP);
394     LL_RCC_PLL3_SetQ(UTILS_PLLsInitStruct->PLL3.PLLQ);
395     LL_RCC_PLL3_SetR(UTILS_PLLsInitStruct->PLL3.PLLR);
396 
397     LL_RCC_PLL3FRACV_Disable();
398     LL_RCC_PLL3_SetFRACV(UTILS_PLLsInitStruct->PLL3.PLLFRACV);
399     LL_RCC_PLL3FRACV_Enable();
400 
401     LL_RCC_PLL3CSG_Disable();
402 
403     if (vcoinput_freqPLL3 >= UTILS_PLL800_INPUT_MED)
404     {
405       LL_RCC_PLL3_SetIFRGE(LL_RCC_PLL3IFRANGE_1);
406     }
407     else
408     {
409       LL_RCC_PLL3_SetIFRGE(LL_RCC_PLL3IFRANGE_0);
410     }
411 
412     /* Configure PLL4 */
413     LL_RCC_PLL4_SetSource(LL_RCC_PLL4SOURCE_HSE);
414 
415     LL_RCC_PLL4_SetM(UTILS_PLLsInitStruct->PLL4.PLLM);
416     LL_RCC_PLL4_SetN(UTILS_PLLsInitStruct->PLL4.PLLN);
417     LL_RCC_PLL4_SetP(UTILS_PLLsInitStruct->PLL4.PLLP);
418     LL_RCC_PLL4_SetQ(UTILS_PLLsInitStruct->PLL4.PLLQ);
419     LL_RCC_PLL4_SetR(UTILS_PLLsInitStruct->PLL4.PLLR);
420 
421     LL_RCC_PLL4FRACV_Disable();
422     LL_RCC_PLL4_SetFRACV(UTILS_PLLsInitStruct->PLL4.PLLFRACV);
423     LL_RCC_PLL4FRACV_Enable();
424 
425     LL_RCC_PLL4CSG_Disable();
426 
427     if (vcoinput_freqPLL4 >= UTILS_PLL800_INPUT_MED)
428     {
429       LL_RCC_PLL4_SetIFRGE(LL_RCC_PLL4IFRANGE_1);
430     }
431     else
432     {
433       LL_RCC_PLL4_SetIFRGE(LL_RCC_PLL4IFRANGE_0);
434     }
435 
436     /* Calculate the new PLL output frequency */
437 #if defined(CORE_CM4)
438     pllfreq = UTILS_GetPLLOutputFrequency(HSEFrequency, &UTILS_PLLsInitStruct->PLL3);
439 #else
440 #if defined(CORE_CA7)
441     pllfreq = UTILS_GetPLLOutputFrequency(HSEFrequency, &UTILS_PLLsInitStruct->PLL1);
442 #endif /* CORE_CA7 */
443 #endif /* CORE_CM4 */
444 
445     /* Enable PLL and switch system clock to PLL */
446     UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
447   }
448   else
449   {
450     /* Current PLL configuration cannot be modified */
451     status = ERROR;
452   }
453 
454   return status;
455 }
456 
457 /**
458   * @}
459   */
460 
461 /**
462   * @}
463   */
464 
465 /** @addtogroup UTILS_LL_Private_Functions
466   * @{
467   */
468 
469 /**
470   * @brief  Function to check PLL parameters
471   * @param  UTILS_PLLStruct pointer to a @ref LL_UTILS_PLLTypeDef
472   *         structure that contains the configuration information for the PLL.
473   * @retval None
474   */
UTILS_CheckPLLParameters(LL_UTILS_PLLTypeDef * UTILS_PLLStruct)475 void UTILS_CheckPLLParameters(LL_UTILS_PLLTypeDef *UTILS_PLLStruct)
476 {
477   /* Check the parameters */
478   assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLStruct->PLLM));
479   assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLStruct->PLLN));
480   assert_param(IS_LL_UTILS_PLLP_VALUE(UTILS_PLLStruct->PLLP));
481   assert_param(IS_LL_UTILS_FRACV_VALUE(UTILS_PLLStruct->PLLFRACV));
482 }
483 
484 /**
485   * @brief  Function to check that PLL can be modified
486   * @param  PLL_InputFrequency  PLL input frequency (in Hz)
487   * @param  UTILS_PLLStruct pointer to a @ref LL_UTILS_PLLTypeDef
488   *         structure that contains the configuration information for the PLL.
489   * @retval PLL output frequency (in Hz)
490   */
UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,LL_UTILS_PLLTypeDef * UTILS_PLLStruct)491 static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLTypeDef *UTILS_PLLStruct)
492 {
493   uint32_t pllfreq;
494 
495   /* Check the parameters */
496   UTILS_CheckPLLParameters(UTILS_PLLStruct);
497 
498   pllfreq = LL_RCC_CalcPLLClockFreq(PLL_InputFrequency,
499                                     UTILS_PLLStruct->PLLM,
500                                     UTILS_PLLStruct->PLLN,
501                                     UTILS_PLLStruct->PLLFRACV,
502                                     UTILS_PLLStruct->PLLP);
503 
504   return pllfreq;
505 }
506 
507 /**
508   * @brief  Check that all PLLs are ready therefore configuration can be done
509   * @retval An ErrorStatus enumeration value:
510   *          - SUCCESS: All PLLs are ready so configuration can be done
511   *          - ERROR: One PLL at least is busy
512   */
UTILS_IsPLLsReady(void)513 static ErrorStatus UTILS_IsPLLsReady(void)
514 {
515   ErrorStatus status = SUCCESS;
516 
517   /* Check if one of the PLL1 is busy */
518   if (LL_RCC_PLL1_IsReady() != 0U)
519   {
520     /* PLL1 configuration cannot be done */
521     status = ERROR;
522   }
523 
524   /* Check if one of the PLL2 is busy */
525   if (LL_RCC_PLL2_IsReady() != 0U)
526   {
527     /* PLL2 configuration cannot be done */
528     status = ERROR;
529   }
530 
531   /* Check if one of the PLL3 is busy */
532   if (LL_RCC_PLL3_IsReady() != 0U)
533   {
534     /* PLL3 configuration cannot be done */
535     status = ERROR;
536   }
537 
538   /* Check if one of the PLL4 is busy */
539   if (LL_RCC_PLL4_IsReady() != 0U)
540   {
541     /* PLL4 configuration cannot be done */
542     status = ERROR;
543   }
544 
545   return status;
546 }
547 
548 /**
549   * @brief  Function to enable PLL and switch system core clock to PLL
550   * @param  SYSCLK_CoreFrequency SYSCLK frequency
551   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef
552   *         structure that contains the configuration information for the BUS
553   *         prescalers.
554   * @retval None
555   */
UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_CoreFrequency,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)556 static void UTILS_EnablePLLAndSwitchSystem(
557   uint32_t SYSCLK_CoreFrequency,
558   LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
559 {
560   assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
561   assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider));
562   assert_param(IS_LL_UTILS_APB3_DIV(UTILS_ClkInitStruct->APB3CLKDivider));
563   assert_param(IS_LL_UTILS_APB4_DIV(UTILS_ClkInitStruct->APB4CLKDivider));
564   assert_param(IS_LL_UTILS_APB5_DIV(UTILS_ClkInitStruct->APB5CLKDivider));
565 
566 
567   /* Enable PLL1 */
568   LL_RCC_PLL1_Enable();
569   while (LL_RCC_PLL1_IsReady() != 1U)
570   {
571     /* Wait for PLL1 ready */
572   }
573   LL_RCC_PLL1P_Enable();
574 
575   /* Enable PLL2 */
576   LL_RCC_PLL2_Enable();
577   while (LL_RCC_PLL2_IsReady() != 1U)
578   {
579     /* Wait for PLL2 ready */
580   }
581   LL_RCC_PLL2P_Enable();
582   LL_RCC_PLL2Q_Enable();
583   LL_RCC_PLL2R_Enable();
584 
585   /* Enable PLL3 */
586   LL_RCC_PLL3_Enable();
587   while (LL_RCC_PLL3_IsReady() != 1U)
588   {
589     /* Wait for PLL3 ready */
590   }
591   LL_RCC_PLL3P_Enable();
592   LL_RCC_PLL3Q_Enable();
593   LL_RCC_PLL3R_Enable();
594 
595   /* Enable PLL4 */
596   LL_RCC_PLL4_Enable();
597   while (LL_RCC_PLL4_IsReady() != 1U)
598   {
599     /* Wait for PLL4 ready */
600   }
601   LL_RCC_PLL4P_Enable();
602   LL_RCC_PLL4Q_Enable();
603   LL_RCC_PLL4R_Enable();
604 
605   /* Set All APBxPrescaler to the Highest Divider */
606   LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_16);
607   LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_16);
608   LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_16);
609   LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_16);
610   LL_RCC_SetAPB5Prescaler(LL_RCC_APB5_DIV_16);
611 
612   /* Set MPU Clock Selection */
613   LL_RCC_SetMPUClkSource(LL_RCC_MPU_CLKSOURCE_PLL1);
614   while (LL_RCC_GetMPUClkSource() != LL_RCC_MPU_CLKSOURCE_PLL1)
615   {}
616 
617   /* Set AXI Sub-System Clock Selection */
618   LL_RCC_SetAXISSClkSource(LL_RCC_AXISS_CLKSOURCE_PLL2);
619   while (LL_RCC_GetAXISSClkSource() != LL_RCC_AXISS_CLKSOURCE_PLL2)
620   {}
621 
622   /* Set MCU Sub-System Clock Selection */
623   LL_RCC_SetMCUSSClkSource(LL_RCC_MCUSS_CLKSOURCE_PLL3);
624   while (LL_RCC_GetMCUSSClkSource() != LL_RCC_MCUSS_CLKSOURCE_PLL3)
625   {}
626 
627   /* Set APBn prescaler*/
628   LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
629   LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider);
630   LL_RCC_SetAPB3Prescaler(UTILS_ClkInitStruct->APB3CLKDivider);
631   LL_RCC_SetAPB4Prescaler(UTILS_ClkInitStruct->APB4CLKDivider);
632   LL_RCC_SetAPB5Prescaler(UTILS_ClkInitStruct->APB5CLKDivider);
633 
634   /* Update SystemCoreClock variable */
635   LL_SetSystemCoreClock(SYSCLK_CoreFrequency);
636 }
637 
638 /**
639   * @}
640   */
641 
642 /**
643   * @}
644   */
645 
646 /**
647   * @}
648   */
649 
650