1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2018 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_msmc.h"
10 #include "clock_config.h"
11
12 /*******************************************************************************
13 * Variables
14 ******************************************************************************/
15 /*
16 * SYSOSC clock ROM setting.
17 * SYSOSC clock : 24MHz
18 * SOSCDIV1_CLK output : 0MHz (async platform clock)
19 * SOSCDIV2_CLK output : 0MHz (async bus clock)
20 * SOSCDIV3_CLK output : 0MHz (async slow clock)
21 */
22 const scg_sosc_config_t g_scgSysOscConfig = {.freq = BOARD_XTAL0_CLK_HZ,
23 .enableMode = kSCG_SysOscEnable,
24 .monitorMode = kSCG_SysOscMonitorDisable,
25 .div1 = kSCG_AsyncClkDisable,
26 .div2 = kSCG_AsyncClkDisable,
27 .div3 = kSCG_AsyncClkDisable,
28 .workMode = kSCG_SysOscModeOscLowPower};
29
30 /*
31 * SIRC clock ROM setting.
32 * SIRC clock : 16MHz
33 * SIRCDIV1_CLK output : 0MHz (async platform clock)
34 * SIRCDIV2_CLK output : 0MHz (async bus clock)
35 * SIRCDIV3_CLK output : 0MHz (async slow clock)
36 */
37 const scg_sirc_config_t g_scgSircConfig = {.enableMode = kSCG_SircEnable | kSCG_SircEnableInLowPower,
38 .div1 = kSCG_AsyncClkDisable,
39 .div2 = kSCG_AsyncClkDisable,
40 .div3 = kSCG_AsyncClkDisable,
41 .range = kSCG_SircRangeHigh};
42
43 /*
44 * FIRC clock ROM setting.
45 * FIRC clock : 48MHz
46 * FIRCDIV1_CLK output : 0MHz (async platform clock)
47 * FIRCDIV2_CLK output : 0MHz (async bus clock)
48 * FIRCDIV3_CLK output : 0MHz (async slow clock)
49 */
50 const scg_firc_config_t g_scgFircConfig = {.enableMode = kSCG_FircEnable,
51 .div1 = kSCG_AsyncClkDisable,
52 .div2 = kSCG_AsyncClkDisable,
53 .div3 = kSCG_AsyncClkDisable,
54 .range = kSCG_FircRange48M,
55 .trimConfig = NULL};
56
57 /*
58 * SYSPLL clock setting.
59 * SYSPLL clock PFD0 : 480 * 18 / 15 = 576MHz
60 * SYSPLLDIV1_CLK output : 0MHz (async platform clock)
61 * SYSPLLDIV2_CLK output : 0MHz (async bus clock)
62 * SYSPLLDIV3_CLK output : 0MHz (async slow clock)
63 * PLL main clock as sync system clock
64 */
65 const scg_spll_config_t g_scgSysPllConfig = {.enableMode = kSCG_SysPllEnable,
66 .div1 = kSCG_AsyncClkDisable,
67 .div2 = kSCG_AsyncClkDisable,
68 .div3 = kSCG_AsyncClkDisable,
69 .src = kSCG_SysPllSrcSysOsc,
70 .isPfdSelected = true,
71 .prediv = 0U,
72 .pfdClkout = kSCG_SysPllPfd0Clk,
73 .mult = 3U}; /* x20 */
74
75 /*
76 * AUXPLL clock setting.
77 * AUXPLL clock : 540.672MHz / 44 = 12.288MHz
78 * AUXPLLDIV1_CLK output : 12.288MHz (async platform clock)
79 * AUXPLLDIV2_CLK output : 12.288MHz (async bus clock)
80 * AUXPLLDIV3_CLK output : 0MHz (async slow clock)
81 */
82 const scg_apll_config_t g_scgAuxPllConfig = {.enableMode = kSCG_AuxPllEnable,
83 .div1 = kSCG_AsyncClkDivBy1,
84 .div2 = kSCG_AsyncClkDivBy1,
85 .div3 = kSCG_AsyncClkDisable,
86 .src = kSCG_AuxPllSrcSysOsc,
87 .isPfdSelected = false,
88 .prediv = 0U,
89 .pfdClkout = kSCG_AuxPllPfd0Clk,
90 .mult = 22U,
91 .pllPostdiv1 = kSCG_SysClkDivBy11,
92 .pllPostdiv2 = kSCG_SysClkDivBy4,
93 .num = 528000U,
94 .denom = 1000000U}; /* 24 x 22.528 = 540.672MHz */
95
96 /*
97 * Select SIRC as system clock source, before configuring other clock sources.
98 * Clock source : SIRC
99 * Core clock : 16MHz
100 * Platform clock : 16MHz
101 * Bus clock : 16MHz
102 * Slow clock : 8MHz
103 */
104 const scg_sys_clk_config_t g_sysClkConfigSircSource = {
105 .divCore = kSCG_SysClkDivBy1, /* Core clock divider. */
106 .divPlat = kSCG_SysClkDivBy1, /* Platform clock divider. */
107 .divBus = kSCG_SysClkDivBy1, /* Bus clock divider. */
108 .divSlow = kSCG_SysClkDivBy2, /* Slow clock divider. */
109 .src = kSCG_SysClkSrcSirc /* System clock source. */
110 };
111
112 /*
113 * System clock source and divider in Normal RUN mode.
114 *
115 * Clock source : SYSPLL main clock 576MHz
116 * Core clock : 115.2MHz
117 * Platform clock : 115.2MHz
118 * Bus clock : 57.6MHz
119 * Slow clock : 19.2MHz
120 */
121 const scg_sys_clk_config_t g_sysClkConfigNormalRun = {
122 .divCore = kSCG_SysClkDivBy5, /* Core clock divider. */
123 .divPlat = kSCG_SysClkDivBy1, /* Platform clock divider. */
124 .divBus = kSCG_SysClkDivBy2, /* Bus clock divider. */
125 .divSlow = kSCG_SysClkDivBy6, /* Slow clock divider. */
126 .src = kSCG_SysClkSrcSysPll /* System clock source. */
127 };
128
129 /*
130 * System clock source and divider for RUN mode, it is used to prepare for switch to HSRUN mode,to make sure HSRUN
131 * switch frequency range
132 * is not bigger than x2.
133 * Clock source : SYSPLL main clock 576MHz
134 * Core clock : 96MHz
135 * Platform clock : 192MHz
136 * Bus clock : 48MHz
137 * Slow clock : 24MHz
138 */
139 const scg_sys_clk_config_t g_sysClkConfigRunToHsrun = {
140 .divCore = kSCG_SysClkDivBy6, /* Core clock divider. */
141 .divPlat = kSCG_SysClkDivBy1, /* Platform clock divider. */
142 .divBus = kSCG_SysClkDivBy4, /* Bus clock divider. */
143 .divSlow = kSCG_SysClkDivBy8, /* Slow clock divider. */
144 .src = kSCG_SysClkSrcSysPll /* System clock source. */
145 };
146
147 /*
148 * System clock source and divider in HSRUN mode.
149 * Clock source : SYSPLL main clock 576MHz
150 * Core clock : 192MHz
151 * Platform clock : 192MHz
152 * Bus clock : 96MHz
153 * Slow clock : 24MHz
154 */
155 const scg_sys_clk_config_t g_sysClkConfigHsrun = {
156 .divCore = kSCG_SysClkDivBy3, /* Core clock divider. */
157 .divPlat = kSCG_SysClkDivBy1, /* Platform clock divider. */
158 .divBus = kSCG_SysClkDivBy2, /* Bus clock divider. */
159 .divSlow = kSCG_SysClkDivBy8, /* Slow clock divider. */
160 .src = kSCG_SysClkSrcSysPll /* System clock source. */
161 };
162
163 /*
164 * System clock source and divider in VLPR mode.
165 * Clock source : SIRC
166 * Core clock : 16MHz
167 * Platform clock : 16MHz
168 * Bus clock : 16MHz
169 * Slow clock : 8MHz
170 */
171 const scg_sys_clk_config_t g_sysClkConfigVlpr = {
172 .divCore = kSCG_SysClkDivBy1, /* Core clock divider. */
173 .divPlat = kSCG_SysClkDivBy1, /* Platform clock divider. */
174 .divBus = kSCG_SysClkDivBy1, /* Bus clock divider. */
175 .divSlow = kSCG_SysClkDivBy2, /* Slow clock divider. */
176 .src = kSCG_SysClkSrcSirc /* System clock source. */
177 };
178
179 /*******************************************************************************
180 * Code
181 ******************************************************************************/
AT_QUICKACCESS_SECTION_CODE(void BOARD_SetRunMode (SCG_Type * scg,uint32_t scgRunConfig,QuadSPI_Type * qspi,clock_ip_name_t qspiClock,uint32_t qspiClockConfig))182 AT_QUICKACCESS_SECTION_CODE(void BOARD_SetRunMode(
183 SCG_Type *scg, uint32_t scgRunConfig, QuadSPI_Type *qspi, clock_ip_name_t qspiClock, uint32_t qspiClockConfig))
184 {
185 int32_t i;
186
187 if (qspi)
188 {
189 volatile uint32_t *pcc = (volatile uint32_t *)qspiClock;
190
191 /* Wait until QSPI is not busy */
192 while (qspi->SR & QuadSPI_SR_BUSY_MASK)
193 {
194 }
195
196 /* Disable module */
197 qspi->MCR |= QuadSPI_MCR_MDIS_MASK;
198
199 *pcc = 0; /* Disable clock before changing clock source */
200
201 /* Update system clock. */
202 scg->RCCR = scgRunConfig;
203
204 /* Wait for clock source switch finished. */
205 while ((scg->CSR & SCG_CSR_SCS_MASK) != (scgRunConfig & SCG_CSR_SCS_MASK))
206 {
207 }
208
209 /* Configure QSPI clock again. */
210 *pcc = qspiClockConfig;
211 /* Re-enable QSPI module */
212 qspi->MCR &= ~QuadSPI_MCR_MDIS_MASK;
213 /* Reset QSPI module */
214 qspi->MCR |= QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK;
215 /* Wait enough cycles until the ahb domain and serial flash domain are reset */
216 for (i = 0; i < 200; i++)
217 {
218 qspi->SR;
219 }
220 /* Clear the reset bits. */
221 qspi->MCR &= ~(QuadSPI_MCR_SWRSTHD_MASK | QuadSPI_MCR_SWRSTSD_MASK);
222 }
223 else
224 {
225 scg->RCCR = scgRunConfig;
226
227 /* Wait for clock source switch finished. */
228 while ((scg->CSR & SCG_CSR_SCS_MASK) != (scgRunConfig & SCG_CSR_SCS_MASK))
229 {
230 }
231 }
232 }
233
BOARD_IsRunOnQSPI(void)234 bool BOARD_IsRunOnQSPI(void)
235 {
236 if (((uint32_t)BOARD_BootClockRUN >= 0x04000000U) && ((uint32_t)BOARD_BootClockRUN < 0x0C000000U))
237 {
238 return true;
239 }
240 return false;
241 }
242
BOARD_InitClock(void)243 static void BOARD_InitClock(void)
244 {
245 /* First initialize same clock settings as ROM does. It's necessary for debugging
246 in case ROM doesn't initialize well. */
247 if (!CLOCK_IsSircValid())
248 {
249 CLOCK_InitSirc(&g_scgSircConfig);
250 }
251
252 if (!CLOCK_IsFircValid())
253 {
254 CLOCK_InitFirc(&g_scgFircConfig);
255 }
256
257 if (!CLOCK_IsSysOscValid())
258 {
259 CLOCK_InitSysOsc(&g_scgSysOscConfig);
260 }
261
262 CLOCK_SetXtal0Freq(BOARD_XTAL0_CLK_HZ);
263
264 /* SOSC, FIRC and SIRC needed by Cortex-A core when M4 runs into VLPR or STOP */
265 SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCLPEN_MASK | SCG_SOSCCSR_SOSCSTEN_MASK;
266 SCG0->FIRCCSR |= SCG_FIRCCSR_FIRCLPEN_MASK | SCG_FIRCCSR_FIRCSTEN_MASK;
267 SCG0->SIRCCSR |= SCG_SIRCCSR_SIRCLPEN_MASK | SCG_SIRCCSR_SIRCSTEN_MASK;
268
269 /* Then set SOSC, FIRC and SIRC DIV needed by application */
270 CLOCK_SetSysOscAsyncClkDiv(kSCG_AsyncDiv1Clk, kSCG_AsyncClkDivBy1);
271 CLOCK_SetSysOscAsyncClkDiv(kSCG_AsyncDiv2Clk, kSCG_AsyncClkDivBy1);
272
273 CLOCK_SetFircAsyncClkDiv(kSCG_AsyncDiv1Clk, kSCG_AsyncClkDivBy1);
274 CLOCK_SetFircAsyncClkDiv(kSCG_AsyncDiv2Clk, kSCG_AsyncClkDivBy1);
275
276 CLOCK_SetSircAsyncClkDiv(kSCG_AsyncDiv1Clk, kSCG_AsyncClkDivBy1);
277 CLOCK_SetSircAsyncClkDiv(kSCG_AsyncDiv2Clk, kSCG_AsyncClkDivBy1);
278 }
279
280 /*
281 * Clock in VLPR mode:
282 * SYSOSC : Enable (shared by CA7)
283 * SIRC : Enable (shared by CA7)
284 * FIRC : Enable (shared by CA7)
285 * SYSPLL : Disable
286 * AUXPLL : Disable
287 */
BOARD_BootClockVLPR(void)288 void BOARD_BootClockVLPR(void)
289 {
290 uint32_t *config = (uint32_t *)(&g_sysClkConfigVlpr);
291 scg_sys_clk_config_t curConfig;
292 QuadSPI_Type *qspi = BOARD_IsRunOnQSPI() ? QuadSPI0 : NULL;
293
294 BOARD_InitClock();
295
296 /* Change to use SIRC as RUN system clock source */
297 /* BOARD_SetRunMode is running in TCM to avoid clock change issue on QSPI memory */
298 BOARD_SetRunMode(SCG0, *config, qspi, kCLOCK_Qspi,
299 PCC1_PCC_QSPI_OTFAD_CGC_MASK | PCC1_PCC_QSPI_OTFAD_PCS(2)); /* QSPI source: 16M SIRC Async */
300
301 /* Change to use SIRC as VLPR system clock source */
302 CLOCK_SetVlprModeSysClkConfig(&g_sysClkConfigVlpr);
303
304 /* Switch running mode to VLPR */
305 SMC_SetPowerModeProtection(MSMC0, kSMC_AllowPowerModeAll);
306 SMC_SetPowerModeVlpr(MSMC0);
307 while (SMC_GetPowerModeState(MSMC0) != kSMC_PowerStateVlpr)
308 {
309 }
310
311 /* Wait for clock source switch finished. */
312 do
313 {
314 CLOCK_GetCurSysClkConfig(&curConfig);
315 } while (curConfig.src != g_sysClkConfigVlpr.src);
316
317 CLOCK_DeinitSysPll();
318 CLOCK_DeinitAuxPll();
319
320 SystemCoreClockUpdate();
321 }
322
323 /*
324 * Clock in RUN mode:
325 * SYSOSC : Enable
326 * SIRC : Enable
327 * FIRC : Enable
328 * SYSPLL : Enable
329 * AUXPLL : Enable
330 */
BOARD_BootClockRUN(void)331 void BOARD_BootClockRUN(void)
332 {
333 uint32_t *config = (uint32_t *)(&g_sysClkConfigVlpr);
334 QuadSPI_Type *qspi = BOARD_IsRunOnQSPI() ? QuadSPI0 : NULL;
335
336 BOARD_InitClock();
337
338 /* Change to use SIRC as system clock source to prepare to initialize other clock sources */
339 /* BOARD_SetRunMode is running in TCM to avoid clock change issue on QSPI memory */
340 BOARD_SetRunMode(SCG0, *config, qspi, kCLOCK_Qspi,
341 PCC1_PCC_QSPI_OTFAD_CGC_MASK | PCC1_PCC_QSPI_OTFAD_PCS(2)); /* QSPI source: 16M SIRC Async */
342
343 /* Initialize SysPll 480MHz */
344 CLOCK_InitSysPll(&g_scgSysPllConfig);
345
346 /* Enable SysPll Pfd0 576MHz */
347 CLOCK_EnableSysPllPfdClkout(kSCG_SysPllPfd0Clk, 15U);
348 /* Enable SysPll Pfd3 480MHz (same as SysPll main clock) */
349 CLOCK_EnableSysPllPfdClkout(kSCG_SysPllPfd3Clk, 18U);
350
351 /* Initialize AuxPll */
352 CLOCK_InitAuxPll(&g_scgAuxPllConfig);
353 /* Enable AuxPll Pfd0 540.672MHz (same as AuxPll before postdiv) */
354 CLOCK_EnableAuxPllPfdClkout(kSCG_AuxPllPfd0Clk, 18U);
355
356 config = (uint32_t *)(&g_sysClkConfigNormalRun);
357 BOARD_SetRunMode(SCG0, *config, qspi, kCLOCK_Qspi,
358 PCC1_PCC_QSPI_OTFAD_CGC_MASK | PCC1_PCC_QSPI_OTFAD_PCS(3)); /* QSPI source: 48M FIRC Async */
359
360 SystemCoreClockUpdate();
361 }
362
363 /*
364 * Clock in HSRUN mode:
365 * SYSOSC : Enable
366 * SIRC : Enable
367 * FIRC : Enable
368 * SYSPLL : Enable
369 * AUXPLL : Enable
370 * NOTE: MAKE SURE PMC0 HSRUN VOLTAGE IS PROPERLY SET BEFORE CALLING THIS FUNCTION.
371 */
BOARD_BootClockHSRUN(void)372 void BOARD_BootClockHSRUN(void)
373 {
374 /* In HSRUN mode, the maximum allowable change in frequency of the system/bus/core/flash is
375 * restricted to x2, to follow this restriction, enter HSRUN mode should follow:
376 * 1.set the run mode to a safe configurations.
377 * 2.set the PLL or FLL output target frequency for HSRUN mode.
378 * 3.switch RUN mode configuration.
379 * 4.switch to HSRUN mode.
380 * 5.switch to HSRUN mode target requency value.
381 */
382
383 scg_sys_clk_config_t curConfig;
384
385 uint32_t *config = (uint32_t *)(&g_sysClkConfigVlpr);
386 QuadSPI_Type *qspi = BOARD_IsRunOnQSPI() ? QuadSPI0 : NULL;
387
388 BOARD_InitClock();
389
390 /* Change to use SIRC as system clock source to prepare to initialize other clock sources */
391 /* BOARD_SetRunMode is running in TCM to avoid clock change issue on QSPI memory */
392 BOARD_SetRunMode(SCG0, *config, qspi, kCLOCK_Qspi,
393 PCC1_PCC_QSPI_OTFAD_CGC_MASK | PCC1_PCC_QSPI_OTFAD_PCS(2)); /* QSPI source: 16M SIRC Async */
394
395 /* Initialize SysPll 480MHz */
396 CLOCK_InitSysPll(&g_scgSysPllConfig);
397
398 /* Enable SysPll Pfd0 576MHz */
399 CLOCK_EnableSysPllPfdClkout(kSCG_SysPllPfd0Clk, 15U);
400 /* Enable SysPll Pfd3 480MHz (same as SysPll main clock) */
401 CLOCK_EnableSysPllPfdClkout(kSCG_SysPllPfd3Clk, 18U);
402
403 /* Initialize AuxPll */
404 CLOCK_InitAuxPll(&g_scgAuxPllConfig);
405 /* Enable AuxPll Pfd0 540.672MHz (same as AuxPll before postdiv) */
406 CLOCK_EnableAuxPllPfdClkout(kSCG_AuxPllPfd0Clk, 18U);
407
408 config = (uint32_t *)(&g_sysClkConfigRunToHsrun);
409
410 BOARD_SetRunMode(SCG0, *config, qspi, kCLOCK_Qspi,
411 PCC1_PCC_QSPI_OTFAD_CGC_MASK | PCC1_PCC_QSPI_OTFAD_PCS(3)); /* QSPI source: 48M FIRC Async */
412
413 /* Switch running mode to HSRUN */
414 SMC_SetPowerModeProtection(MSMC0, kSMC_AllowPowerModeAll);
415 SMC_SetPowerModeHsrun(MSMC0);
416 while (SMC_GetPowerModeState(MSMC0) != kSMC_PowerStateHsrun)
417 {
418 }
419
420 /* Change to use SysPll as system clock source */
421 CLOCK_SetHsrunModeSysClkConfig(&g_sysClkConfigHsrun);
422 /* Wait for clock source switch finished. */
423 do
424 {
425 CLOCK_GetCurSysClkConfig(&curConfig);
426 } while (curConfig.src != g_sysClkConfigHsrun.src);
427
428 SystemCoreClockUpdate();
429 }
430