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