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