1 /*
2 * Copyright (c) 2021, NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Note: this file is linked to RAM. Any functions called while changing clocks
7 * to the flexspi modules must be linked to RAM, or within this file
8 */
9
10 #include <zephyr/init.h>
11 #include <power_rt10xx.h>
12 #include <zephyr/kernel.h>
13 #include <fsl_clock.h>
14
15 /*
16 * Clock configuration structures populated at boot time. These structures are
17 * used to reinitialize the PLLs after exiting low power mode.
18 */
19 #ifdef CONFIG_INIT_ARM_PLL
20 static clock_arm_pll_config_t arm_pll_config;
21 #endif
22 #ifdef CONFIG_INIT_VIDEO_PLL
23 static clock_video_pll_config_t video_pll_config;
24 #endif
25 #ifdef CONFIG_INIT_ENET_PLL
26 static clock_enet_pll_config_t enet_pll_config;
27 #endif
28 static clock_sys_pll_config_t sys_pll_config;
29 static clock_usb_pll_config_t usb1_pll_config;
30
31 #define IMX_RT_SYS_PFD_FRAC(reg, pfd_num) \
32 (((reg) >> (8U * pfd_num)) &\
33 CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
34 #define IMX_RT_USB1_PFD_FRAC(reg, pfd_num) \
35 (((reg) >> (8U * pfd_num)) &\
36 CCM_ANALOG_PFD_480_PFD0_FRAC_MASK)
37
38 uint8_t sys_pll_pfd0_frac;
39 uint8_t sys_pll_pfd1_frac;
40 uint8_t sys_pll_pfd2_frac;
41 uint8_t sys_pll_pfd3_frac;
42
43 uint8_t usb1_pll_pfd1_frac;
44 uint8_t usb1_pll_pfd2_frac;
45 uint8_t usb1_pll_pfd3_frac;
46
47 uint32_t flexspi_div;
48
49 /*
50 * Duplicate implementation of CLOCK_SetMux() provided by SDK. This function
51 * must be linked to ITCM, as it will be used to change the clocks of the
52 * FLEXSPI and SEMC peripherals.
53 * Any function called from this function must also reside in ITCM
54 */
clock_set_mux(clock_mux_t mux,uint32_t value)55 static void clock_set_mux(clock_mux_t mux, uint32_t value)
56 {
57 uint32_t busy_shift;
58
59 busy_shift = (uint32_t)CCM_TUPLE_BUSY_SHIFT(mux);
60 CCM_TUPLE_REG(CCM, mux) = (CCM_TUPLE_REG(CCM, mux) & (~CCM_TUPLE_MASK(mux))) |
61 (((uint32_t)((value) << CCM_TUPLE_SHIFT(mux))) & CCM_TUPLE_MASK(mux));
62
63 /* Clock switch need Handshake? */
64 if (busy_shift != CCM_NO_BUSY_WAIT) {
65 /* Wait until CCM internal handshake finish. */
66 while ((CCM->CDHIPR & ((1UL << busy_shift))) != 0UL) {
67 }
68 }
69 }
70
71 /*
72 * Duplicate implementation of CLOCK_SetDiv() provided by SDK. This function
73 * must be linked to ITCM, as it will be used to change the clocks of the
74 * FLEXSPI and SEMC peripherals.
75 * Any function called from this function must also reside in ITCM
76 */
clock_set_div(clock_div_t divider,uint32_t value)77 static void clock_set_div(clock_div_t divider, uint32_t value)
78 {
79 uint32_t busy_shift;
80
81 busy_shift = CCM_TUPLE_BUSY_SHIFT(divider);
82 CCM_TUPLE_REG(CCM, divider) = (CCM_TUPLE_REG(CCM, divider) & (~CCM_TUPLE_MASK(divider))) |
83 (((uint32_t)((value) << CCM_TUPLE_SHIFT(divider))) & CCM_TUPLE_MASK(divider));
84
85 /* Clock switch need Handshake? */
86 if (busy_shift != CCM_NO_BUSY_WAIT) {
87 /* Wait until CCM internal handshake finish. */
88 while ((CCM->CDHIPR & ((uint32_t)(1UL << busy_shift))) != 0UL) {
89 }
90 }
91 }
92
93 /*
94 * Duplicate implementation of CLOCK_InitUsb1Pll() provided by SDK. This function
95 * must be linked to ITCM, as it will be used to change the clocks of the
96 * FLEXSPI and SEMC peripherals.
97 * Any function called from this function must also reside in ITCM
98 */
clock_init_usb1_pll(const clock_usb_pll_config_t * config)99 static void clock_init_usb1_pll(const clock_usb_pll_config_t *config)
100 {
101 /* Bypass PLL first */
102 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) |
103 CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src);
104
105 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) |
106 CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK |
107 CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK |
108 CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider);
109
110 while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0UL) {
111 ;
112 }
113
114 /* Disable Bypass */
115 CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK;
116 }
117
flexspi_enter_critical(void)118 static void flexspi_enter_critical(void)
119 {
120 #if CONFIG_CODE_FLEXSPI2
121 /* Wait for flexspi to be inactive, and gate the clock */
122 while (!((FLEXSPI2->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) &&
123 (FLEXSPI2->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) {
124 }
125 FLEXSPI2->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
126
127 /* Disable clock gate of flexspi2. */
128 CCM->CCGR7 &= (~CCM_CCGR7_CG1_MASK);
129 #elif CONFIG_CODE_FLEXSPI
130 /* Wait for flexspi to be inactive, and gate the clock */
131 while (!((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) &&
132 (FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) {
133 }
134 FLEXSPI->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
135
136 /* Disable clock of flexspi. */
137 CCM->CCGR6 &= (~CCM_CCGR6_CG5_MASK);
138 #endif
139 }
140
flexspi_exit_critical(void)141 static void flexspi_exit_critical(void)
142 {
143 #if CONFIG_CODE_FLEXSPI2
144 /* Enable clock gate of flexspi2. */
145 CCM->CCGR7 |= (CCM_CCGR7_CG1_MASK);
146
147 FLEXSPI2->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
148 FLEXSPI2->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
149 while (FLEXSPI2->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) {
150 }
151 while (!((FLEXSPI2->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) &&
152 (FLEXSPI2->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) {
153 }
154 #elif CONFIG_CODE_FLEXSPI
155 /* Enable clock of flexspi. */
156 CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
157
158 FLEXSPI->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
159 FLEXSPI->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
160 while (FLEXSPI->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) {
161 }
162 while (!((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) &&
163 (FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) {
164 }
165 #endif
166 /* Invalidate I-cache after flexspi clock changed. */
167 if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) {
168 SCB_InvalidateICache();
169 }
170 }
171
172
clock_full_power(void)173 void clock_full_power(void)
174 {
175 /* Power up PLLS */
176 /* Set arm PLL div to divide by 2*/
177 clock_set_div(kCLOCK_ArmDiv, 1);
178 #ifdef CONFIG_INIT_ARM_PLL
179 /* Reinit arm pll based on saved configuration */
180 CLOCK_InitArmPll(&arm_pll_config);
181 #endif
182
183 #ifdef CONFIG_INIT_VIDEO_PLL
184 /* Reinit video pll */
185 CLOCK_InitVideoPll(&video_pll_config);
186 #endif
187
188 #ifdef CONFIG_INIT_ENET_PLL
189 /* Reinit enet pll */
190 CLOCK_InitEnetPll(&enet_pll_config);
191 #endif
192 /* Init SYS PLL */
193 CLOCK_InitSysPll(&sys_pll_config);
194
195 /* Enable USB PLL PFD 1 2 3 */
196 CLOCK_InitUsb1Pfd(kCLOCK_Pfd1, usb1_pll_pfd1_frac);
197 CLOCK_InitUsb1Pfd(kCLOCK_Pfd2, usb1_pll_pfd2_frac);
198 CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, usb1_pll_pfd3_frac);
199
200 /* Enable SYS PLL PFD0 1 2 3 */
201 CLOCK_InitSysPfd(kCLOCK_Pfd0, sys_pll_pfd0_frac);
202 CLOCK_InitSysPfd(kCLOCK_Pfd1, sys_pll_pfd1_frac);
203 CLOCK_InitSysPfd(kCLOCK_Pfd2, sys_pll_pfd2_frac);
204 CLOCK_InitSysPfd(kCLOCK_Pfd3, sys_pll_pfd3_frac);
205
206 /* Switch to full speed clocks */
207 #if (defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1))
208 flexspi_enter_critical();
209 #endif
210
211 /* Set Flexspi divider before increasing frequency of PLL3 PDF0. */
212 #if CONFIG_CODE_FLEXSPI
213 clock_set_div(kCLOCK_FlexspiDiv, flexspi_div);
214 clock_set_mux(kCLOCK_FlexspiMux, 3);
215 #elif CONFIG_CODE_FLEXSPI2
216 clock_set_div(kCLOCK_Flexspi2Div, flexspi_div);
217 clock_set_mux(kCLOCK_Flexspi2Mux, 1);
218 #endif
219 /* Init USB1 PLL. This will disable the PLL3 bypass. */
220 clock_init_usb1_pll(&usb1_pll_config);
221
222 /* Switch SEMC clock to PLL2_PFD2 clock */
223 clock_set_mux(kCLOCK_SemcMux, 1);
224
225 /* CORE CLK to 600MHz, AHB, IPG to 150MHz, PERCLK to 75MHz */
226 clock_set_div(kCLOCK_PerclkDiv, 1);
227 clock_set_div(kCLOCK_IpgDiv, 3);
228 clock_set_div(kCLOCK_AhbDiv, 0);
229 /* PERCLK mux to IPG CLK */
230 clock_set_mux(kCLOCK_PerclkMux, 0);
231 /* MUX to ENET_500M (RT1010-1024) / ARM_PODF (RT1050-1064) */
232 clock_set_mux(kCLOCK_PrePeriphMux, 3);
233 /* PERIPH mux to periph clock 2 output */
234 clock_set_mux(kCLOCK_PeriphMux, 0);
235
236 #if (defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1))
237 flexspi_exit_critical();
238 #endif
239
240 }
241
clock_low_power(void)242 void clock_low_power(void)
243 {
244 #if (defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1))
245 flexspi_enter_critical();
246 #endif
247 /* Switch to 24MHz core clock, so ARM PLL can power down */
248 clock_set_div(kCLOCK_PeriphClk2Div, 0);
249 /* Switch to OSC clock */
250 clock_set_mux(kCLOCK_PeriphClk2Mux, 1);
251 /* Switch peripheral mux to 24MHz source */
252 clock_set_mux(kCLOCK_PeriphMux, 1);
253 /* Set PLL3 to bypass mode, output 24M clock */
254 CCM_ANALOG->PLL_USB1_SET = CCM_ANALOG_PLL_USB1_BYPASS_MASK;
255 CCM_ANALOG->PLL_USB1_SET = CCM_ANALOG_PLL_USB1_ENABLE_MASK;
256 CCM_ANALOG->PFD_480_CLR = CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK;
257 /* Change flexspi to use PLL3 PFD0 with no divisor (24M flexspi clock) */
258 #if CONFIG_CODE_FLEXSPI
259 clock_set_div(kCLOCK_FlexspiDiv, 0);
260 /* FLEXSPI1 mux to PLL3 PFD0 BYPASS */
261 clock_set_mux(kCLOCK_FlexspiMux, 3);
262 #elif CONFIG_CODE_FLEXSPI2
263 clock_set_div(kCLOCK_Flexspi2Div, 0);
264 /* FLEXSPI2 mux to PLL3 PFD0 BYPASS */
265 clock_set_mux(kCLOCK_Flexspi2Mux, 1);
266 #endif
267 /* CORE CLK to 24MHz and AHB, IPG, PERCLK to 12MHz */
268 clock_set_div(kCLOCK_PerclkDiv, 0);
269 clock_set_div(kCLOCK_IpgDiv, 1);
270 clock_set_div(kCLOCK_AhbDiv, 0);
271 /* PERCLK mux to IPG CLK */
272 clock_set_mux(kCLOCK_PerclkMux, 0);
273 /* Switch SEMC clock to peripheral clock */
274 clock_set_mux(kCLOCK_SemcMux, 0);
275 #if (defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1))
276 flexspi_exit_critical();
277 #endif
278 /* After switching clocks, it is safe to power down the PLLs */
279 #ifdef CONFIG_INIT_ARM_PLL
280 /* Deinit ARM PLL */
281 CLOCK_DeinitArmPll();
282 #endif
283 /* Deinit SYS PLL */
284 CLOCK_DeinitSysPll();
285
286 /* Deinit SYS PLL PFD 0 1 2 3 */
287 CLOCK_DeinitSysPfd(kCLOCK_Pfd0);
288 CLOCK_DeinitSysPfd(kCLOCK_Pfd1);
289 CLOCK_DeinitSysPfd(kCLOCK_Pfd2);
290 CLOCK_DeinitSysPfd(kCLOCK_Pfd3);
291
292
293 /* Deinit USB1 PLL PFD 1 2 3 */
294 CLOCK_DeinitUsb1Pfd(kCLOCK_Pfd1);
295 CLOCK_DeinitUsb1Pfd(kCLOCK_Pfd2);
296 CLOCK_DeinitUsb1Pfd(kCLOCK_Pfd3);
297
298 /* Deinit VIDEO PLL */
299 CLOCK_DeinitVideoPll();
300
301 /* Deinit ENET PLL */
302 CLOCK_DeinitEnetPll();
303 }
304
clock_lpm_init(void)305 void clock_lpm_init(void)
306 {
307 uint32_t tmp_reg = 0;
308
309 CLOCK_SetMode(kCLOCK_ModeRun);
310 /* Enable RC OSC. It needs at least 4ms to be stable, so self tuning need to be enabled. */
311 XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK;
312 /* Configure RC OSC */
313 XTALOSC24M->OSC_CONFIG0 = XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR(0x4) |
314 XTALOSC24M_OSC_CONFIG0_SET_HYST_MINUS(0x2) |
315 XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG(0xA7) |
316 XTALOSC24M_OSC_CONFIG0_START_MASK |
317 XTALOSC24M_OSC_CONFIG0_ENABLE_MASK;
318 XTALOSC24M->OSC_CONFIG1 = XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR(0x40) |
319 XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG(0x2DC);
320 /* Take some delay */
321 SDK_DelayAtLeastUs(4000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
322 /* Add some hysteresis */
323 tmp_reg = XTALOSC24M->OSC_CONFIG0;
324 tmp_reg &= ~(XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK |
325 XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK);
326 tmp_reg |= XTALOSC24M_OSC_CONFIG0_HYST_PLUS(3) | XTALOSC24M_OSC_CONFIG0_HYST_MINUS(3);
327 XTALOSC24M->OSC_CONFIG0 = tmp_reg;
328 /* Set COUNT_1M_TRG */
329 tmp_reg = XTALOSC24M->OSC_CONFIG2;
330 tmp_reg &= ~XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK;
331 tmp_reg |= XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG(0x2d7);
332 XTALOSC24M->OSC_CONFIG2 = tmp_reg;
333 /* Hardware requires to read OSC_CONFIG0 or OSC_CONFIG1 to make OSC_CONFIG2 write work */
334 tmp_reg = XTALOSC24M->OSC_CONFIG1;
335 XTALOSC24M->OSC_CONFIG1 = tmp_reg;
336 }
337
imxrt_lpm_init(void)338 static int imxrt_lpm_init(void)
339 {
340
341 struct clock_callbacks callbacks;
342 uint32_t usb1_pll_pfd0_frac;
343
344 callbacks.clock_set_run = clock_full_power;
345 callbacks.clock_set_low_power = clock_low_power;
346 callbacks.clock_lpm_init = clock_lpm_init;
347
348 /*
349 * Read the boot time configuration of all PLLs.
350 * This is required because not all PLLs preserve register state
351 * when powered down. Additionally, populating these configuration
352 * structures enables the rest of the code to use the fsl_clock HAL api.
353 */
354 #ifdef CONFIG_INIT_ARM_PLL
355 /* Read configuration values for arm pll */
356 arm_pll_config.src = ((CCM_ANALOG->PLL_ARM &
357 CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK) >>
358 CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_SHIFT);
359 arm_pll_config.loopDivider = ((CCM_ANALOG->PLL_ARM &
360 CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK) >>
361 CCM_ANALOG_PLL_ARM_DIV_SELECT_SHIFT);
362 #endif
363 /* Read configuration values for sys pll */
364 sys_pll_config.src = ((CCM_ANALOG->PLL_SYS &
365 CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK) >>
366 CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_SHIFT);
367 sys_pll_config.loopDivider = ((CCM_ANALOG->PLL_SYS &
368 CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK) >>
369 CCM_ANALOG_PLL_SYS_DIV_SELECT_SHIFT);
370 sys_pll_config.numerator = CCM_ANALOG->PLL_SYS_NUM;
371 sys_pll_config.denominator = CCM_ANALOG->PLL_SYS_DENOM;
372 sys_pll_config.ss_step = ((CCM_ANALOG->PLL_SYS_SS &
373 CCM_ANALOG_PLL_SYS_SS_STEP_MASK) >>
374 CCM_ANALOG_PLL_SYS_SS_STEP_SHIFT);
375 sys_pll_config.ss_enable = ((CCM_ANALOG->PLL_SYS_SS &
376 CCM_ANALOG_PLL_SYS_SS_ENABLE_MASK) >>
377 CCM_ANALOG_PLL_SYS_SS_ENABLE_SHIFT);
378 sys_pll_config.ss_stop = ((CCM_ANALOG->PLL_SYS_SS &
379 CCM_ANALOG_PLL_SYS_SS_STOP_MASK) >>
380 CCM_ANALOG_PLL_SYS_SS_STOP_SHIFT);
381
382 /* Read configuration values for usb1 pll */
383 usb1_pll_config.src = ((CCM_ANALOG->PLL_USB1 &
384 CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK) >>
385 CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_SHIFT);
386 usb1_pll_config.loopDivider = ((CCM_ANALOG->PLL_USB1 &
387 CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) >>
388 CCM_ANALOG_PLL_USB1_DIV_SELECT_SHIFT);
389 #ifdef CONFIG_INIT_VIDEO_PLL
390 /* Read configuration values for video pll */
391 video_pll_config.src = ((CCM_ANALOG->PLL_VIDEO &
392 CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC_MASK) >>
393 CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC_SHIFT);
394 video_pll_config.loopDivider = ((CCM_ANALOG->PLL_VIDEO &
395 CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK) >>
396 CCM_ANALOG_PLL_VIDEO_DIV_SELECT_SHIFT);
397 video_pll_config.numerator = CCM_ANALOG->PLL_VIDEO_NUM;
398 video_pll_config.denominator = CCM_ANALOG->PLL_VIDEO_DENOM;
399 switch ((CCM_ANALOG->PLL_VIDEO &
400 CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT_MASK) >>
401 CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT_SHIFT) {
402 case 0:
403 video_pll_config.postDivider = 16;
404 break;
405 case 1:
406 if (CCM_ANALOG->MISC2 & CCM_ANALOG_MISC2_VIDEO_DIV(3)) {
407 video_pll_config.postDivider = 8;
408 } else {
409 video_pll_config.postDivider = 2;
410 }
411 break;
412 case 2:
413 if (CCM_ANALOG->MISC2 & CCM_ANALOG_MISC2_VIDEO_DIV(3)) {
414 video_pll_config.postDivider = 4;
415 } else {
416 video_pll_config.postDivider = 1;
417 }
418 break;
419 default:
420 video_pll_config.postDivider = 1;
421 }
422 #endif
423 #if CONFIG_INIT_ENET_PLL
424 enet_pll_config.src = ((CCM_ANALOG->PLL_ENET &
425 CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_MASK) >>
426 CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_SHIFT);
427 enet_pll_config.loopDivider = ((CCM_ANALOG->PLL_ENET &
428 CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK) >>
429 CCM_ANALOG_PLL_ENET_DIV_SELECT_SHIFT);
430 enet_pll_config.loopDivider1 = ((CCM_ANALOG->PLL_ENET &
431 CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_MASK) >>
432 CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_SHIFT);
433 enet_pll_config.enableClkOutput = (CCM_ANALOG->PLL_ENET &
434 CCM_ANALOG_PLL_ENET_ENABLE_MASK);
435 enet_pll_config.enableClkOutput1 = (CCM_ANALOG->PLL_ENET &
436 CCM_ANALOG_PLL_ENET_ENET2_REF_EN_MASK);
437 enet_pll_config.enableClkOutput25M = (CCM_ANALOG->PLL_ENET &
438 CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK);
439 #endif
440
441 /* Record all pll PFD values that we intend to disable in low power mode */
442 sys_pll_pfd0_frac = IMX_RT_SYS_PFD_FRAC(CCM_ANALOG->PFD_528, kCLOCK_Pfd0);
443 sys_pll_pfd1_frac = IMX_RT_SYS_PFD_FRAC(CCM_ANALOG->PFD_528, kCLOCK_Pfd1);
444 sys_pll_pfd2_frac = IMX_RT_SYS_PFD_FRAC(CCM_ANALOG->PFD_528, kCLOCK_Pfd2);
445 sys_pll_pfd3_frac = IMX_RT_SYS_PFD_FRAC(CCM_ANALOG->PFD_528, kCLOCK_Pfd3);
446
447 usb1_pll_pfd0_frac = IMX_RT_USB1_PFD_FRAC(CCM_ANALOG->PFD_480, kCLOCK_Pfd0);
448 /* The target full power frequency for the flexspi clock is ~100MHz.
449 * Use the PFD0 value currently set to calculate the div we should use for
450 * the full power flexspi div
451 * PFD output frequency formula = (480 * 18) / pfd0_frac
452 * flexspi div formula = FLOOR((480*18) / (pfd0_frac * target_full_power_freq))
453 */
454 flexspi_div = (480 * 18) / (usb1_pll_pfd0_frac * 100);
455
456
457 usb1_pll_pfd1_frac = IMX_RT_USB1_PFD_FRAC(CCM_ANALOG->PFD_480, kCLOCK_Pfd1);
458 usb1_pll_pfd2_frac = IMX_RT_USB1_PFD_FRAC(CCM_ANALOG->PFD_480, kCLOCK_Pfd2);
459 usb1_pll_pfd3_frac = IMX_RT_USB1_PFD_FRAC(CCM_ANALOG->PFD_480, kCLOCK_Pfd3);
460
461 /* Install LPM callbacks */
462 imxrt_clock_pm_callbacks_register(&callbacks);
463 return 0;
464 }
465
466
467 SYS_INIT(imxrt_lpm_init, PRE_KERNEL_1, 0);
468