1 /*
2  * Copyright 2020-2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "clock_config.h"
9 #include "board.h"
10 #include "fsl_upower.h"
11 
12 /*******************************************************************************
13  ************************ BOARD_InitBootClocks function ************************
14  ******************************************************************************/
BOARD_InitBootClocks(void)15 void BOARD_InitBootClocks(void)
16 {
17     BOARD_BootClockRUN();
18 }
19 
20 /*******************************************************************************
21  * Variables
22  ******************************************************************************/
23 
24 /*
25  * SYSOSC clock setting.
26  * SYSOSC clock         : 24MHz
27  */
28 const cgc_sosc_config_t g_cgcSysOscConfig = {.freq        = BOARD_XTAL0_CLK_HZ,
29                                              .enableMode  = 0, /* Disabled in Deep Sleep/Power down */
30                                              .monitorMode = kCGC_SysOscMonitorDisable,
31                                              .workMode    = kCGC_SysOscModeOscLowPower};
32 
33 /*
34  * FRO clock setting.
35  * FRO clock            : 192MHz
36  */
37 const cgc_fro_config_t g_cgcFroConfig = {.enableMode = 0 /*0 - FRO is disabled in Sleep/Deep Sleep Modes*/};
38 
39 /*
40  * MAX FREQ:
41  * PLL0 VCO: 480 MHz
42  * PLL0 PFD0: 400 MHz
43  * PLL0 PFD1: 480 MHz
44  * PLL0 PFD2: 480 MHz
45  * PLL0 PFD3: 400 MHz
46  *
47  * PLL0 clock setting.
48  * PLL0 clock VCO       : 24 * 20 = 480MHz
49  * PLL0 VCODIV output   : 0MHz
50  * PLL0 PFD1DIV output  : 0MHz
51  * PLL0 PFD2DIV output  : 0MHz
52  */
53 const cgc_pll0_config_t g_cgcPll0Config = {.enableMode = kCGC_PllEnable,
54                                            .div1 = 0U,
55                                            .pfd1Div = 0U,
56                                            .pfd2Div = 0U,
57                                            .src = kCGC_PllSrcSysOsc,
58                                            .mult = kCGC_Pll0Mult20
59                                           }; /* x20 */
60 
61 /*
62  * MAX FREQ:
63  * PLL1 VCO: 542 MHz
64  * PLL1 PFD0: 432 MHz
65  * PLL1 PFD1: 400 MHz
66  * PLL1 PFD2: 542 MHz
67  * PLL1 PFD3: 480 MHz
68  *
69  * PLL1 clock setting.
70  * PLL1 clock VCO       : 24 * 22.528 = 540.672MHz
71  * PLL1 VCODIV output   : 0MHz
72  * PLL1 PFD1DIV output  : 0MHz
73  * PLL1 PFD2DIV output  : 540.672 / 44 = 12.288MHz
74  */
75 const cgc_pll1_config_t g_cgcPll1Config = {.enableMode = kCGC_PllEnable,
76                                            .div1 = 0U,
77                                            .pfd1Div = 0U,
78                                            .pfd2Div = 44U,
79                                            .src = kCGC_PllSrcSysOsc,
80                                            .mult = kCGC_Pll1Mult22,
81                                            .num = 528000U,
82                                            .denom = 1000000U};
83 
84 /*
85  * Select FRO as system clock source, before configuring other clock sources.
86  * Clock source   : FRO
87  * Core clock     : 192 / (0 + 1) = 192MHz
88  * Bus clock      : 192 / ((0 + 1) * (1 + 1)) = 96MHz
89  * Slow clock     : 192 / ((0 + 1) * (1 + 3)) = 48MHz
90  */
91 cgc_rtd_sys_clk_config_t g_sysClkConfigFroSource = {
92     .divCore = 0, /* Core clock divider. */
93     .divBus  = 1, /* Bus clock divider. */
94     .divSlow = 3, /* Slow clock divider. */
95     .src     = kCGC_RtdSysClkSrcFro, /* System clock source. */
96     .locked  = 0, /* Register not locked. */
97 };
98 
99 // clang-format off
100 /*
101  * Note: CM33 slow clock must be slower and an integer division of CM33 system IP bus.
102  * System clock source and divider in Normal RUN mode.
103  *
104  * Clock source   : PLL0 main clock 480 MHz.
105  * Core clock     : 480 / (2 + 1) = 160 MHz
106  * Bus clock      : 480 / ((2 + 1) * (2 + 1)) = 53.33 MHz
107  * Slow clock     : 480 / ((2 + 1) * (8 + 1)) = 17.77778 MHz
108  *
109  * Clock source   : PLL0PFD0 main clock 392.7272 MHz.
110  * Core clock     : 392.7272 / (1 + 1) = 196.3636 MHz
111  * Bus clock      : 392.7272 / ((1 + 1) * (1 + 1)) = 98.1818 MHz
112  * Slow clock     : 392.7272 / ((1 + 1) * (9 + 1)) = 19.63636 MHz
113  *
114  * Clock source   : PLL1PFD0 main clock 423.134608 MHz.
115  * Core clock     : 423.134608 / (1 + 1) = 211.567304 MHz
116  * Bus clock      : 423.134608 / ((1 + 1) * (1 + 1)) = 105.783652 MHz
117  * Slow clock     : 423.134608 / ((1 + 1) * (9 + 1)) =  21.1567304 MHz
118  *
119  * Clock source   : PLL1PFD0 main clock 405.504 MHz.
120  * Core clock     : 405.504 / (1 + 1) = 202.752 MHz
121  * Bus clock      : 405.504 / ((1 + 1) * (1 + 1)) = 101.376 MHz
122  * Slow clock     : 405.504 / ((1 + 1) * (9 + 1)) = 20.2752 MHz
123  *
124  * Clock source   : PLL1PFD0 main clock 389.28384 MHz.
125  * Core clock     : 389.28384 / (1 + 1) =  194.64192 MHz
126  * Bus clock      : 389.28384 / ((1 + 1) * (1 + 1)) = 97.32096 MHz
127  * Slow clock     : 389.28384 / ((1 + 1) * (9 + 1)) = 21.62688 MHz
128  * +---------------------------------------------------------------------------------------------------------------------------------------+
129  * |  RTD Power Mode |    Biasing Option |  Drive Mode | Max CM33_CORECLK freq/MHz | Max CM33_BUSCLK freq/MHz |  Max CM33_SLOWCLK freq/MHz |
130  * -----------------------------------------------------------------------------------------------------------------------------------------
131  * |    ACTIVE       |        ARBB       |     UD      |        38.4               |         20               |          12.5              |
132  * -----------------------------------------------------------------------------------------------------------------------------------------
133  * |    ACTIVE       |        AFBB       |     ND      |        160                |         65               |           20               |
134  * -----------------------------------------------------------------------------------------------------------------------------------------
135  * |    ACTIVE       |        AFBB       |     OD      |        216                |         108              |           24               |
136  * +---------------------------------------------------------------------------------------------------------------------------------------+
137  *
138  */
139 // clang-format on
140 #define SELECT_PLL0PFD0_AS_SOURCE_CLK (0)
141 #define SELECT_PLL1PFD0_AS_SOURCE_CLK (0)
142 //#define SELECT_PLL1PFD0_AS_SOURCE_CLK (1)
143 cgc_rtd_sys_clk_config_t g_sysClkConfigRun = {
144 #if SELECT_PLL0PFD0_AS_SOURCE_CLK
145     .divBus  = 1,   /* Bus clock divider. */
146     .divSlow = 9,   /* Slow clock divider. */
147     .src     = kCGC_RtdSysClkSrcPll0Pfd0, /* PLL0PFD0 main clock source. */
148     .divCore = 1,   /* Core clock divider. */
149 #elif SELECT_PLL1PFD0_AS_SOURCE_CLK
150     .divBus  = 1,   /* Bus clock divider. */
151     .divSlow = 9,   /* Slow clock divider. */
152     .src     = kCGC_RtdSysClkSrcPll1Pfd0, /* PLL1PFD0 main clock source. */
153     .divCore = 1,   /* Core clock divider. */
154 #else
155     .divBus  = 1,   /* Bus clock divider. */
156     .divSlow = 7,   /* Slow clock divider. */
157     .src     = kCGC_RtdSysClkSrcPll0, /* PLL0 main clock source. */
158     .divCore = 2,   /* Core clock divider. */
159 #endif
160     .locked  = 0, /* Register not locked. */
161 };
162 
163 static cgc_rtd_sys_clk_src_t clk_src[] = {
164     kCGC_RtdSysClkSrcFro,
165     kCGC_RtdSysClkSrcLvds,
166     kCGC_RtdSysClkSrcLvds,
167 };
168 /*******************************************************************************
169  * Code
170  ******************************************************************************/
BOARD_InitClock(void)171 void BOARD_InitClock(void)
172 {
173     CLOCK_InitFro(&g_cgcFroConfig);
174 
175     if (!CLOCK_IsSysOscValid())
176     {
177         CLOCK_InitSysOsc(&g_cgcSysOscConfig);
178     }
179 
180     CLOCK_SetXtal0Freq(BOARD_XTAL0_CLK_HZ);
181 
182     /* Then set SOSC, FRO DIV needed by application */
183     CLOCK_SetRtdSysOscAsyncClkDiv(kCGC_AsyncDiv1Clk, 1);
184     CLOCK_SetRtdSysOscAsyncClkDiv(kCGC_AsyncDiv2Clk, 1);
185     CLOCK_SetRtdSysOscAsyncClkDiv(kCGC_AsyncDiv3Clk, 0);
186 
187     CLOCK_SetRtdFroAsyncClkDiv(kCGC_AsyncDiv1Clk, 1);
188     CLOCK_SetRtdFroAsyncClkDiv(kCGC_AsyncDiv2Clk, 1);
189     CLOCK_SetRtdFroAsyncClkDiv(kCGC_AsyncDiv3Clk, 0);
190 
191     /* RTC OSC clock is enabled by default, but spin till it is stable */
192     while(!CLOCK_IsRtcOscValid())
193     {
194     }
195     CLOCK_SetXtal32Freq(CLK_RTC_32K_CLK);
196 }
197 
BOARD_CalculateDivider(uint32_t src_freq,uint32_t dest_freq,int * divider)198 void BOARD_CalculateDivider(uint32_t src_freq, uint32_t dest_freq, int * divider)
199 {
200     uint32_t div = 1;
201 
202     if (divider != NULL)
203     {
204         while ((src_freq / div) > dest_freq)
205         {
206             div++;
207         }
208 
209         *divider = div;
210     }
211 }
212 
BOARD_InitPlls(void)213 void BOARD_InitPlls(void)
214 {
215     /* Initialize PLL0 480MHz */
216     CLOCK_InitPll0(&g_cgcPll0Config);
217 
218     /* Enable Pll0 Pfd0(MAX Freq is 400 MHz) 392.7272 MHz = (18 * 480) / 22 */
219     CLOCK_EnablePll0PfdClkout(kCGC_PllPfd0Clk, 22U);
220     /* Enable Pll0 Pfd1(MAX Freq is 480 MHz) 480 MHz = (18 * 480) / 18 */
221     CLOCK_EnablePll0PfdClkout(kCGC_PllPfd1Clk, 18U);
222     /* Enable Pll0 Pfd2(MAX Freq is 480 MHz) 480MHz */
223     CLOCK_EnablePll0PfdClkout(kCGC_PllPfd2Clk, 18U);
224     /* Enable Pll0 Pfd3(MAX Freq is 400 MHz) 392.7272 MHz = (18 * 480) / 22 */
225     CLOCK_EnablePll0PfdClkout(kCGC_PllPfd3Clk, 22U);
226 
227     /* Initialize PLL1(MAX Freq is 542 MHz) 540.672 MHz */
228     CLOCK_InitPll1(&g_cgcPll1Config);
229     /* Enable Pll1 Pfd0(MAX Freq is 432 MHz) 423.134608 MHz = (18 * 540.672) / 23 */
230     CLOCK_EnablePll1PfdClkout(kCGC_PllPfd0Clk, 23U);
231     /* Enable Pll1 Pfd2(MAX Freq is 542 MHz) 540.672MHz */
232     CLOCK_EnablePll1PfdClkout(kCGC_PllPfd2Clk, 18U);
233 }
234 
235 /*
236  * Clock in RUN mode:
237  * SYSOSC  : Enable
238  * FRO    : Enable
239  * FIRC    : Enable
240  * PLL0  : Enable
241  * AUXPLL  : Enable
242  *
243  * Note:
244  *     Pls decrease cortex-m33's clock frequency before decreasing voltage.
245  *     Pls increase voltage before increasing cortex-m33's clock frequency.
246  */
BOARD_BootClockRUN(void)247 void BOARD_BootClockRUN(void)
248 {
249     int freq_divider = 1;
250 
251     UPOWER_Init(NULL);
252     BOARD_InitClock();
253 
254     /* default voltage is 1.0 V for Real Time Domain, default cortex-m33's clock frequency is 92 MHz(clock source is FRO192CLK, div is 1, so 192 MHz / (1 + 1) = 96 MHz) */
255 
256     /* Call function BOARD_FlexspiClockSafeConfig() to move FlexSPI clock to a stable clock source to avoid
257        instruction/data fetch issue when updating PLL and Main clock if XIP(execute code on FLEXSPI memory). */
258     BOARD_FlexspiClockSafeConfig();
259 
260     BOARD_InitPlls();
261 
262     BOARD_UpdateM33CoreFreq(&g_sysClkConfigRun);
263 
264     /*
265      * Call function BOARD_SetFlexspiClock() to set user configured clock source/divider for FlexSPI.
266      * 5 - CM33 CORE/PLAT CLK
267      */
268     BOARD_CalculateDivider(SystemCoreClock, BOARD_NOR_FLASH_READ_MAXIMUM_FREQ, &freq_divider);
269     BOARD_SetFlexspiClock(FLEXSPI0, 5U, freq_divider - 1, 0U); /* flexspi0's clock is CM33_PLATCLK / div */
270 }
271 
272 /*
273  * Init Clock after system exit from Power Down:
274  * SYSOSC  : Enable
275  * FRO    : Enable
276  * FIRC    : Enable
277  * PLL0  : Enable
278  * AUXPLL  : Enable
279  */
BOARD_ResumeClockInit(void)280 void BOARD_ResumeClockInit(void)
281 {
282     uint32_t tmp_clk_cfg = 0U;
283     uint32_t new_freq = 0U;
284     uint32_t current_freq = CLOCK_GetFreq(kCLOCK_Cm33CorePlatClk); /* get cm33 core/platform clock frequency */
285     int freq_divider = 1;
286 
287     memcpy(&tmp_clk_cfg, &g_sysClkConfigRun, sizeof(g_sysClkConfigRun));
288     new_freq = CLOCK_GetRtdSysClkFreq(tmp_clk_cfg, kCGC_SysClkCorePlat);
289 
290     if (current_freq != new_freq)
291     {
292         BOARD_InitClock();
293 
294         /*
295 	 * Call function BOARD_FlexspiClockSafeConfig() to move FlexSPI clock to a stable clock source to avoid
296          * instruction/data fetch issue when updating PLL and Main clock if XIP(execute code on FLEXSPI memory).
297 	 */
298         BOARD_FlexspiClockSafeConfig();
299 
300         BOARD_InitPlls();
301 
302         BOARD_UpdateM33CoreFreq(&g_sysClkConfigRun);
303 
304         /*
305          * Call function BOARD_SetFlexspiClock() to set user configured clock source/divider for FlexSPI.
306          * 5 - CM33 CORE/PLAT CLK
307          */
308         BOARD_CalculateDivider(SystemCoreClock, BOARD_NOR_FLASH_READ_MAXIMUM_FREQ, &freq_divider);
309         BOARD_SetFlexspiClock(FLEXSPI0, 5U, freq_divider - 1, 0U); /* flexspi0's clock is CM33_PLATCLK / div */
310         /* Reinitialize debug console */
311         BOARD_InitDebugConsole();
312     }
313 }
314 
BOARD_CalculateCoreClkDivider(cgc_rtd_sys_clk_src_t clk_src,int * core_clk_divider,int * bus_clk_divider,int * slow_clk_divider,drive_mode_e drive_mode)315 drive_mode_e BOARD_CalculateCoreClkDivider(cgc_rtd_sys_clk_src_t clk_src, int *core_clk_divider, int *bus_clk_divider, int *slow_clk_divider, drive_mode_e drive_mode)
316 {
317     drive_mode_e new_drive_mode = drive_mode;
318     const rtd_sys_clk_src_and_clk_name_t clk_src_and_clk_name[] = {
319         {kCGC_RtdSysClkSrcFro, kCLOCK_FroClk},
320         {kCGC_RtdSysClkSrcPll0Pfd0, kCLOCK_Pll0Pfd0Clk},
321         {kCGC_RtdSysClkSrcPll1Pfd0, kCLOCK_Pll1Pfd0Clk},
322         {kCGC_RtdSysClkSrcSysOsc, kCLOCK_SysOscClk},
323         {kCGC_RtdSysClkSrcRtcOsc, kCLOCK_RtcOscClk},
324         {kCGC_RtdSysClkSrcLvds, kCLOCK_LvdsClk},
325         {kCGC_RtdSysClkSrcPll0, kCLOCK_Pll0Clk}
326     };
327 
328     // clang-format off
329     /*
330      * +---------------------------------------------------------------------------------------------------------------------------------------+
331      * |  RTD Power Mode |    Biasing Option |  Drive Mode | Max CM33_CORECLK freq/MHz | Max CM33_BUSCLK freq/MHz |  Max CM33_SLOWCLK freq/MHz |
332      * -----------------------------------------------------------------------------------------------------------------------------------------
333      * |    ACTIVE       |        ARBB       |     UD      |        38.4               |         20               |          12.5              |
334      * -----------------------------------------------------------------------------------------------------------------------------------------
335      * |    ACTIVE       |        AFBB       |     ND      |        160                |         65               |           20               |
336      * -----------------------------------------------------------------------------------------------------------------------------------------
337      * |    ACTIVE       |        AFBB       |     OD      |        216                |         108              |           24               |
338      * +---------------------------------------------------------------------------------------------------------------------------------------+
339      *
340      */
341     // clang-format on
342 
343 
344     drive_mode_and_clk_t drive_mode_and_clk[] = {
345         { DRIVE_MODE_UD, CM33_CORE_MAX_FREQ_UD, CM33_BUS_MAX_FREQ_UD, CM33_SLOW_MAX_FREQ_UD},
346         { DRIVE_MODE_ND, CM33_CORE_MAX_FREQ_ND, CM33_BUS_MAX_FREQ_ND, CM33_SLOW_MAX_FREQ_ND},
347         { DRIVE_MODE_OD, CM33_CORE_MAX_FREQ_OD, CM33_BUS_MAX_FREQ_OD, CM33_SLOW_MAX_FREQ_OD},
348     };
349     uint32_t freq = 0U;
350     cgc_rtd_sys_clk_config_t tmp_sys_clk_cfg;
351     uint32_t tmp_cfg;
352 
353     memset((void *)&tmp_sys_clk_cfg, 0, sizeof(tmp_sys_clk_cfg));
354 
355     freq = CLOCK_GetFreq(clk_src_and_clk_name[(int)clk_src].clk_name);
356 
357     if (core_clk_divider != NULL)
358     {
359         BOARD_CalculateDivider(freq, drive_mode_and_clk[drive_mode].max_core_clk_freq, core_clk_divider);
360         tmp_sys_clk_cfg.src = clk_src;
361         tmp_sys_clk_cfg.divCore = *core_clk_divider - 1;
362         freq /= (*core_clk_divider); /* calculate core clock frequency */
363         if ((slow_clk_divider != NULL) && (bus_clk_divider != NULL))
364         {
365             BOARD_CalculateDivider(freq, drive_mode_and_clk[drive_mode].max_bus_clk_freq, bus_clk_divider);
366             BOARD_CalculateDivider(freq, drive_mode_and_clk[drive_mode].max_slow_clk_freq, slow_clk_divider);
367             /* Note: CM33 slow clock must be slower and an integer division of CM33 system IP bus. */
368             while (((*slow_clk_divider <= *bus_clk_divider) || ((*slow_clk_divider) % (*bus_clk_divider) != 0U)))
369             {
370                 *slow_clk_divider = *slow_clk_divider + 1;
371             }
372             tmp_sys_clk_cfg.divBus = *bus_clk_divider - 1;
373             tmp_sys_clk_cfg.divSlow = *slow_clk_divider - 1;
374         }
375         memcpy(&tmp_cfg, &tmp_sys_clk_cfg, sizeof(tmp_sys_clk_cfg));
376         freq = CLOCK_GetRtdSysClkFreq(tmp_cfg, kCGC_SysClkCorePlat);
377         new_drive_mode = BOARD_GetDriveModeByCoreFreq(freq);
378     }
379 
380     return new_drive_mode;
381 }
382 
BOARD_SwitchToFROClk(drive_mode_e drive_mode)383 drive_mode_e BOARD_SwitchToFROClk(drive_mode_e drive_mode)
384 {
385     drive_mode_e new_drive_mode = drive_mode;
386 
387     /* Switch to FRO when the current clock source is non FRO */
388     if (((CGC_RTD->CM33CLK & CGC_CM33CLK_SCS_MASK) >> CGC_CM33CLK_SCS_SHIFT) != kCGC_RtdSysClkSrcFro)
389     {
390         int core_clk_divider = 0;
391         int bus_clk_divider = 0;
392         int slow_clk_divider = 0;
393 
394         /* Now start to set up FRO clock. */
395         /* Step 1. Configure clock. */
396         CGC_RTD->FROCSR = (uint32_t)g_cgcFroConfig.enableMode;
397 
398         /* Step 2. Wait for FRO clock to be valid. */
399         while (0UL == (CGC_RTD->FROCSR & CGC_FROCSR_FROVLD_MASK))
400         {
401         }
402 
403         if (!CLOCK_IsSysOscValid())
404         {
405             CLOCK_InitSysOsc(&g_cgcSysOscConfig);
406         }
407 
408         new_drive_mode = BOARD_CalculateCoreClkDivider((cgc_rtd_sys_clk_src_t)g_sysClkConfigFroSource.src, &core_clk_divider, &bus_clk_divider, &slow_clk_divider, drive_mode);
409         assert(new_drive_mode == drive_mode);
410         g_sysClkConfigFroSource.divCore = core_clk_divider - 1;
411         g_sysClkConfigFroSource.divBus = bus_clk_divider - 1;
412         g_sysClkConfigFroSource.divSlow = slow_clk_divider - 1;
413         CLOCK_SetCm33SysClkConfig(&g_sysClkConfigFroSource);
414         SystemCoreClockUpdate();
415 
416         for (int i = 0; i < 100; i++)
417         {
418             __asm volatile("NOP");
419         }
420     }
421     return new_drive_mode;
422 }
423 
424 /* Disable PLL0 and PLL1 */
BOARD_DisablePlls(void)425 void BOARD_DisablePlls(void)
426 {
427     /* Disable clocks for power saving */
428     CGC_RTD->PLL0CSR = 0;
429     CGC_RTD->PLL1CSR = 0;
430 }
431 
BOARD_GetRtdDriveMode(void)432 drive_mode_e BOARD_GetRtdDriveMode(void)
433 {
434     static drive_mode_e rtd_drive_mode;
435     int32_t status                   = -1;
436     int voltage                      = 0;
437     uint32_t mask = __get_PRIMASK();
438 
439     (void)status; /*fix build warning when with -Os optimizetion level */
440     /* check the global interrupt whether is enabled */
441     if (mask == 0U)
442     {
443         /* get current drive mode(Accoring to voltage of buck2, buck2 is the supply voltage for RTD Domain) */
444         status                  = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
445         assert(status == 0);
446         switch (voltage)
447         {
448             case PMIC_VOLTAGE_1_1V:
449                 rtd_drive_mode = DRIVE_MODE_OD;
450                 break;
451             case PMIC_VOLTAGE_1_0V:
452                 rtd_drive_mode = DRIVE_MODE_ND;
453                 break;
454             case PMIC_VOLTAGE_0_9V:
455                 rtd_drive_mode = DRIVE_MODE_UD;
456                 break;
457             default:
458                 assert(false);
459                 break;
460         }
461     }
462 
463     return rtd_drive_mode;
464 }
465 
BOARD_GetDriveModeByCoreFreq(uint32_t freq)466 drive_mode_e BOARD_GetDriveModeByCoreFreq(uint32_t freq)
467 {
468     drive_mode_e drive_mode = DRIVE_MODE_ND;
469 
470     if ((freq > CM33_CORE_MAX_FREQ_ND) && (freq <= CM33_CORE_MAX_FREQ_OD))
471     {
472         drive_mode = DRIVE_MODE_OD;
473     }
474     else if ((freq > CM33_CORE_MAX_FREQ_UD) && (freq <= CM33_CORE_MAX_FREQ_ND))
475     {
476         drive_mode = DRIVE_MODE_ND;
477     }
478     else if ((freq > 0U) && (freq <= CM33_CORE_MAX_FREQ_UD))
479     {
480         drive_mode = DRIVE_MODE_UD;
481     }
482     else
483     {
484         assert(false);
485     }
486 
487     return drive_mode;
488 }
489 
BOARD_UpdateM33CoreFreq(cgc_rtd_sys_clk_config_t * config)490 int32_t BOARD_UpdateM33CoreFreq(cgc_rtd_sys_clk_config_t *config)
491 {
492     uint32_t m33_dest_core_frequency = 0;
493     int32_t status                   = -1;
494     int voltage                      = 0;
495     uint32_t tmp_cfg;
496     drive_mode_e drive_mode;
497     int i = 0;
498 
499     for (i = 0; i < ARRAY_SIZE(clk_src); i++)
500     {
501         if (clk_src[i] == kCGC_RtdSysClkSrcLvds)
502         {
503              clk_src[i] = (cgc_rtd_sys_clk_src_t)g_sysClkConfigRun.src;
504              if (i == DRIVE_MODE_OD)
505              {
506                  /* Max freq of Pll1Pfd0 is 432 MHz, the frequency is 423.134608 MHz = (18 * 540.672) / 23(In BOARD_InitPlls()] */
507                  clk_src[i] = kCGC_RtdSysClkSrcPll1Pfd0; /* Use the clock source to provide higher frequency for cortex-m33 */
508              }
509         }
510     }
511     if (BOARD_IS_XIP_FLEXSPI0())
512     {
513         /*
514          * Workaround: For flash target mode, after Mcore resume from Power down mode.
515          * Apply UPOWER_GetPmicVoltage function will cause DDR exit retention process fail.
516          * Try add delay function, it still fail.
517          */
518         pca9460_buck3ctrl_t tmp_buck3_ctrl;
519         pca9460_ldo1_cfg_t tmp_ldo1_cfg;
520 
521         tmp_buck3_ctrl.val = 0U;
522         tmp_ldo1_cfg.val = 0U;
523 
524         UPOWER_ReadPmicReg(PCA9460_BUCK3CTRL_ADDR, &(tmp_buck3_ctrl.val));
525         UPOWER_ReadPmicReg(PCA9460_LDO1_CFG_ADDR, &(tmp_ldo1_cfg.val));
526         UPOWER_ReadPmicReg(PCA9460_BUCK3CTRL_ADDR, &(tmp_buck3_ctrl.val));
527         UPOWER_ReadPmicReg(PCA9460_LDO1_CFG_ADDR, &(tmp_ldo1_cfg.val));
528     }
529 
530     drive_mode = BOARD_GetRtdDriveMode();
531     (void)drive_mode; /* fix warning */
532 
533     memcpy(&tmp_cfg, config, sizeof(cgc_rtd_sys_clk_config_t));
534 
535     /* Get current clock frequency(SystemCoreClock) */
536     SystemCoreClockUpdate();
537     /*
538      * 160 MHz  < m33 core frequency <= 216 MHz: 1.1 V w/AFBB
539      * 38.4 MHz  < m33 core frequency <= 160 MHz: 1.0 V w/AFBB
540      * 0 MHz < m33 core frequency <= 38.4 MHz: 0.9 V w/ARBB
541      */
542     m33_dest_core_frequency = CLOCK_GetRtdSysClkFreq(tmp_cfg, kCGC_SysClkCorePlat);
543     status                  = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
544     if (status == 0)
545     {
546         if (m33_dest_core_frequency < SystemCoreClock)
547         {
548             /* Decrease core frequency */
549             /* Pls decrease cortex-m33's clock frequency before decreasing voltage. */
550 
551             /* check whether need decrease voltage */
552             /* 160 MHz < current core clk of cortex-m33 <= 216 MHz */
553             if (SystemCoreClock > CM33_CORE_MAX_FREQ_ND && SystemCoreClock <= CM33_CORE_MAX_FREQ_OD)
554             {
555                 /* 160 MHz < next core clk for cortex-m33 <= 216 MHz */
556                 if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_ND &&
557                     m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_OD)
558                 {
559                     config->src = clk_src[DRIVE_MODE_OD];
560                     CLOCK_SetCm33SysClkConfig(config);
561                 }
562                 /* 38.4 MHz < next core clk for cortex-m33 <= 160 MHz */
563                 else if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_UD &&
564                          m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_ND)
565                 {
566                     config->src = clk_src[DRIVE_MODE_ND];
567                     CLOCK_SetCm33SysClkConfig(config);
568                     if (voltage != PMIC_VOLTAGE_1_0V)
569                     {
570 	                /* update bias configuration */
571                         status = UPOWER_ChngRTDDomBias(DRIVE_MODE_ND);
572                         assert(status == 0);
573                         status = UPOWER_ChngPmicVoltage(PMIC_BUCK2, PMIC_VOLTAGE_1_0V);
574                         if (status == 0)
575                         {
576                             status = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
577                             if (status == 0 && voltage == PMIC_VOLTAGE_1_0V)
578                             {
579                             }
580                             else
581                             {
582                                 assert(false);
583                             }
584                         }
585                         else
586                         {
587                             assert(false);
588                         }
589                     }
590                 }
591                 /* 0 MHz < next core clk for cortex-m33 <= 38.4 MHz */
592                 else if (m33_dest_core_frequency > 0 &&
593                          m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_UD)
594                 {
595                     config->src = clk_src[DRIVE_MODE_UD];
596                     CLOCK_SetCm33SysClkConfig(config);
597                     if (voltage != PMIC_VOLTAGE_0_9V)
598                     {
599                         /* update bias configuration */
600                         status = UPOWER_ChngRTDDomBias(DRIVE_MODE_UD);
601                         assert(status == 0);
602                         status = UPOWER_ChngPmicVoltage(PMIC_BUCK2, PMIC_VOLTAGE_0_9V);
603                         if (status == 0)
604                         {
605                             status = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
606                             if (status == 0 && voltage == PMIC_VOLTAGE_0_9V)
607                             {
608                             }
609                             else
610                             {
611                                 assert(false);
612                             }
613                         }
614                         else
615                         {
616                             assert(false);
617                         }
618                     }
619                 }
620             }
621             /* 38.4 MHz < current core clk of cortex-m33 <= 160 MHz */
622             else if (SystemCoreClock > CM33_CORE_MAX_FREQ_UD && SystemCoreClock <= CM33_CORE_MAX_FREQ_ND)
623             {
624                 /* 38.4 MHz < next core clk for cortex-m33 <= 160 MHz */
625                 if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_UD &&
626                     m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_ND)
627                 {
628                     config->src = clk_src[DRIVE_MODE_ND];
629                     CLOCK_SetCm33SysClkConfig(config);
630                 }
631                 /* 0 MHz < next core clk for cortex-m33 <= 38.4 MHz */
632                 else if (m33_dest_core_frequency > 0 &&
633                          m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_UD)
634                 {
635                     config->src = clk_src[DRIVE_MODE_UD];
636                     CLOCK_SetCm33SysClkConfig(config);
637                     if (voltage != PMIC_VOLTAGE_0_9V)
638                     {
639                         /* update bias configuration */
640                         status = UPOWER_ChngRTDDomBias(DRIVE_MODE_UD);
641                         assert(status == 0);
642                         status = UPOWER_ChngPmicVoltage(PMIC_BUCK2, PMIC_VOLTAGE_0_9V);
643                         if (status == 0)
644                         {
645                             status = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
646                             if (status == 0 && voltage == PMIC_VOLTAGE_0_9V)
647                             {
648                             }
649                             else
650                             {
651                                 assert(false);
652                             }
653                         }
654                     }
655                 }
656             }
657             /* 0 MHz < current core clk of cortex-m33 <= 38.4 MHz */
658             else if (SystemCoreClock > 0 && SystemCoreClock <= CM33_CORE_MAX_FREQ_UD)
659             {
660                 config->src = clk_src[DRIVE_MODE_UD];
661                 CLOCK_SetCm33SysClkConfig(config);
662             }
663         }
664         else if (m33_dest_core_frequency > SystemCoreClock)
665         {
666             /* Increase voltage from 1.0 V to 1.1 V before increasing cortex-m33's clock frequency */
667             /* check whether need increase voltage */
668             /* 160 MHz < current core clk of cortex-m33 <= 216 MHz */
669             if (SystemCoreClock > CM33_CORE_MAX_FREQ_ND && SystemCoreClock <= CM33_CORE_MAX_FREQ_OD)
670             {
671                 /* 160 MHz < next core clk for cortex-m33 <= 216 MHz */
672                 if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_ND &&
673                     m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_OD)
674                 {
675                     config->src = clk_src[DRIVE_MODE_OD];
676                 }
677             }
678             /* 38.4 MHz < current core clk of cortex-m33 <= 160 MHz */
679             else if (SystemCoreClock > CM33_CORE_MAX_FREQ_UD && SystemCoreClock <= CM33_CORE_MAX_FREQ_ND)
680             {
681                 /* 160 MHz < next core clk for cortex-m33 <= 216 MHz */
682                 if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_ND &&
683                     m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_OD)
684                 {
685                     config->src = clk_src[DRIVE_MODE_OD];
686                     if (voltage != PMIC_VOLTAGE_1_1V)
687                     {
688                         status = UPOWER_ChngPmicVoltage(PMIC_BUCK2, PMIC_VOLTAGE_1_1V);
689                         if (status == 0)
690                         {
691                             status = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
692                         }
693                         else
694                         {
695                             assert(false);
696                         }
697                     }
698                     if (status == 0 && voltage == PMIC_VOLTAGE_1_1V)
699                     {
700                         /* update bias configuration */
701                         status = UPOWER_ChngRTDDomBias(DRIVE_MODE_OD);
702                         assert(status == 0);
703                     }
704                     else
705                     {
706                         assert(false);
707                     }
708                 }
709                 /* 38.4 MHz < next core clk for cortex-m33 <= 160 MHz */
710                 else if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_UD &&
711                          m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_ND)
712                 {
713                     config->src = clk_src[DRIVE_MODE_ND];
714                 }
715             }
716             /* 0 MHz < current core clk of cortex-m33 <= 38.4 MHz */
717             else if (SystemCoreClock > 0 && SystemCoreClock <= CM33_CORE_MAX_FREQ_UD)
718             {
719                 /* 160 MHz < next core clk for cortex-m33 <= 216 MHz */
720                 if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_ND &&
721                     m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_OD)
722                 {
723                     config->src = clk_src[DRIVE_MODE_OD];
724                     if (voltage != PMIC_VOLTAGE_1_1V)
725                     {
726                         status = UPOWER_ChngPmicVoltage(PMIC_BUCK2, PMIC_VOLTAGE_1_1V);
727                         if (status == 0)
728                         {
729                             status = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
730                         }
731                         else
732                         {
733                             assert(false);
734                         }
735                     }
736                     if (status == 0 && voltage == PMIC_VOLTAGE_1_1V)
737                     {
738                         /* update bias configuration */
739                         status = UPOWER_ChngRTDDomBias(DRIVE_MODE_OD);
740                         assert(status == 0);
741                     }
742                     else
743                     {
744                         assert(false);
745                     }
746                 }
747                 /* 38.4 MHz < next core clk for cortex-m33 <= 160 MHz */
748                 else if (m33_dest_core_frequency > CM33_CORE_MAX_FREQ_UD &&
749                          m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_ND)
750                 {
751                     config->src = clk_src[DRIVE_MODE_ND];
752                     if (voltage != PMIC_VOLTAGE_1_0V)
753                     {
754                         status = UPOWER_ChngPmicVoltage(PMIC_BUCK2, PMIC_VOLTAGE_1_0V);
755                         if (status == 0)
756                         {
757                             status = UPOWER_GetPmicVoltage(PMIC_BUCK2, &voltage);
758                         }
759                         else
760                         {
761                             assert(false);
762                         }
763                     }
764                     if (status == 0 && voltage == PMIC_VOLTAGE_1_0V)
765                     {
766                         /* update bias configuration */
767                         status = UPOWER_ChngRTDDomBias(DRIVE_MODE_ND);
768                         assert(status == 0);
769                     }
770                     else
771                     {
772                         assert(false);
773                     }
774                 }
775                 /* 0 MHz < next core clk for cortex-m33 <= 38.4 MHz */
776                 else if (m33_dest_core_frequency > 0 &&
777                          m33_dest_core_frequency <= CM33_CORE_MAX_FREQ_UD)
778                 {
779                     config->src = clk_src[DRIVE_MODE_UD];
780                 }
781             }
782             CLOCK_SetCm33SysClkConfig(config);
783         }
784     }
785 
786     /* update clock frequency */
787     SystemCoreClockUpdate();
788     /* update drive mode */
789     drive_mode = BOARD_GetRtdDriveMode();
790     (void)drive_mode; /* fix warning */
791 
792     return status;
793 }
794 
BOARD_SwitchDriveMode(void)795 void BOARD_SwitchDriveMode(void)
796 {
797     drive_mode_e current_rtd_drive_mode = DRIVE_MODE_OD, next_drive_mode = DRIVE_MODE_ND, new_drive_mode = DRIVE_MODE_ND;
798     int core_clk_divider = 0;
799     int bus_clk_divider = 0;
800     int slow_clk_divider = 0;
801     int status = -1;
802     int freq_divider = 1;
803     cgc_rtd_sys_clk_config_t tmp_sys_clk_cfg;
804     uint32_t buck_idx = PMIC_BUCK2;
805     cgc_rtd_sys_clk_src_t next_clk_src = kCGC_RtdSysClkSrcFro;
806     static int switch_flag = SWITCH_DRIVE_MODE_INIT_STATE; /* 0: initial state; 1: switch from ND to OD; 2: switch from ND to UD; 3: switch from UD to ND; 4: switch from OD to ND */
807 
808     // clang-format off
809     /*
810      * +---------------------------------------------------------------------------------------------------------------------------------------+
811      * |  RTD Power Mode |    Biasing Option |  Drive Mode | Max CM33_CORECLK freq/MHz | Max CM33_BUSCLK freq/MHz |  Max CM33_SLOWCLK freq/MHz |
812      * -----------------------------------------------------------------------------------------------------------------------------------------
813      * |    ACTIVE       |        ARBB       |     UD      |        38.4               |         20               |          12.5              |
814      * -----------------------------------------------------------------------------------------------------------------------------------------
815      * |    ACTIVE       }        AFBB       |     ND      |        160                |         65               |           20               |
816      * -----------------------------------------------------------------------------------------------------------------------------------------
817      * |    ACTIVE       |        AFBB       |     OD      |        216                |         108              |           24               |
818      * +---------------------------------------------------------------------------------------------------------------------------------------+
819      *
820      */
821     // clang-format on
822 
823     // clang-format off
824     /*
825      * state machine for switching drive mode of RTD:
826      * --<----
827      * |     |
828      * UD() -> ND -> OD
829      *       |      |
830      *       ---<----
831      * UD: 0.9 V (only FRO is available for RTD in Under Drive Mode)
832      * ND: 1.0 V
833      * OD: 1.1 V
834      */
835     // clang-format on
836     int voltage[] = {
837         PMIC_VOLTAGE_0_9V,
838 	PMIC_VOLTAGE_1_0V,
839 	PMIC_VOLTAGE_1_1V
840     };
841 
842     (void)status; /*fix build warning when with -Os optimizetion level */
843     memcpy(&tmp_sys_clk_cfg, &g_sysClkConfigRun, sizeof(g_sysClkConfigRun));
844     /* Get current Drive Mode of RTD */
845     current_rtd_drive_mode = BOARD_GetRtdDriveMode();
846     switch (current_rtd_drive_mode)
847     {
848         case DRIVE_MODE_UD:
849             /* UD -> ND */
850             next_drive_mode = DRIVE_MODE_ND;
851             next_clk_src = clk_src[next_drive_mode];
852             new_drive_mode = BOARD_CalculateCoreClkDivider(next_clk_src, &core_clk_divider, &bus_clk_divider, &slow_clk_divider, next_drive_mode);
853             switch_flag = SWITCH_DRIVE_MODE_FROM_UD_TO_ND;
854             break;
855         case DRIVE_MODE_ND:
856 	    if (switch_flag == SWITCH_DRIVE_MODE_INIT_STATE)
857             {
858                  /* from ND -> OD */
859                 next_drive_mode = DRIVE_MODE_OD;
860                 next_clk_src = clk_src[next_drive_mode];
861                 new_drive_mode = BOARD_CalculateCoreClkDivider(next_clk_src, &core_clk_divider, &bus_clk_divider, &slow_clk_divider, next_drive_mode);
862                 if (new_drive_mode == current_rtd_drive_mode)
863                 {
864                     /* from ND -> UD */
865                     next_drive_mode = DRIVE_MODE_UD;
866                     next_clk_src = clk_src[next_drive_mode];
867                     new_drive_mode = BOARD_CalculateCoreClkDivider(next_clk_src, &core_clk_divider, &bus_clk_divider, &slow_clk_divider, next_drive_mode);
868                     switch_flag = SWITCH_DRIVE_MODE_FROM_ND_TO_UD;
869                 }
870                 else
871                 {
872                     switch_flag = SWITCH_DRIVE_MODE_FROM_ND_TO_OD;
873                 }
874             }
875 	    else if (switch_flag == SWITCH_DRIVE_MODE_FROM_OD_TO_ND)
876             {
877                     next_drive_mode = DRIVE_MODE_UD;
878                     next_clk_src = clk_src[next_drive_mode];
879                     new_drive_mode = BOARD_CalculateCoreClkDivider(next_clk_src, &core_clk_divider, &bus_clk_divider, &slow_clk_divider, next_drive_mode);
880                     switch_flag = SWITCH_DRIVE_MODE_FROM_ND_TO_UD;
881             }
882 	    else if (switch_flag == SWITCH_DRIVE_MODE_FROM_UD_TO_ND)
883             {
884                     next_drive_mode = DRIVE_MODE_OD;
885                     next_clk_src = clk_src[next_drive_mode];
886                     new_drive_mode = BOARD_CalculateCoreClkDivider(next_clk_src, &core_clk_divider, &bus_clk_divider, &slow_clk_divider, next_drive_mode);
887                     switch_flag = SWITCH_DRIVE_MODE_FROM_ND_TO_OD;
888             }
889             break;
890         case DRIVE_MODE_OD:
891             /* OD -> ND */
892             next_drive_mode = DRIVE_MODE_ND;
893             next_clk_src = clk_src[next_drive_mode];
894             new_drive_mode = BOARD_CalculateCoreClkDivider(next_clk_src, &core_clk_divider, &bus_clk_divider, &slow_clk_divider, next_drive_mode);
895             switch_flag = SWITCH_DRIVE_MODE_FROM_OD_TO_ND;
896             break;
897         default:
898             assert(false);
899             break;
900     }
901     next_drive_mode = new_drive_mode;
902     g_sysClkConfigRun.divBus = bus_clk_divider - 1;
903     g_sysClkConfigRun.divSlow = slow_clk_divider - 1;
904     g_sysClkConfigRun.divCore = core_clk_divider - 1;
905     g_sysClkConfigRun.src = next_clk_src;
906 
907     /* switch other clock source to FRO to avoid clock glitch issue */
908     if (next_drive_mode > current_rtd_drive_mode)
909     {
910         status = UPOWER_ChngPmicVoltage(buck_idx, voltage[next_drive_mode]);
911         assert(status == 0);
912         new_drive_mode = BOARD_SwitchToFROClk(next_drive_mode);
913         assert(new_drive_mode == next_drive_mode);
914         UPOWER_ChngRTDDomBias(next_drive_mode);
915     }
916     else if (next_drive_mode < current_rtd_drive_mode)
917     {
918         new_drive_mode = BOARD_SwitchToFROClk(next_drive_mode);
919         assert(new_drive_mode == next_drive_mode);
920         status = UPOWER_ChngPmicVoltage(buck_idx, voltage[next_drive_mode]);
921         assert(status == 0);
922         /* Update bias configuration */
923         UPOWER_ChngRTDDomBias(next_drive_mode);
924     }
925     else
926     {
927         new_drive_mode = BOARD_SwitchToFROClk(next_drive_mode);
928         assert(new_drive_mode == next_drive_mode);
929     }
930 
931     /* switch FRO back to other clock source */
932     CLOCK_SetCm33SysClkConfig(&g_sysClkConfigRun);
933     SystemCoreClockUpdate();
934 
935     /*
936      * The cm33 platform clock(core clock) is used as clock source of flexspi0, so reinitialize flexspi0
937      * 5 - CM33 CORE/PLAT CLK
938      */
939     BOARD_CalculateDivider(SystemCoreClock, BOARD_NOR_FLASH_READ_MAXIMUM_FREQ, &freq_divider);
940     BOARD_SetFlexspiClock(FLEXSPI0, 5U, freq_divider - 1, 0U); /* flexspi0's clock is CM33_PLATCLK / div */
941 
942     /* Note: All of IP modules that use CM33_CORECLK, CM33_BUSCLK, CM33_SLOWCLK need be reinitialized again */
943     assert(BOARD_GetRtdDriveMode() == next_drive_mode);
944 }
945