1 /*
2 * Copyright (c) 2021, Laird Connectivity
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/device.h>
8 #include <fsl_clock.h>
9 #include <fsl_common.h>
10 #include <fsl_rdc.h>
11 #include <zephyr/init.h>
12 #include <zephyr/kernel.h>
13 #include <soc.h>
14
15 #include <zephyr/dt-bindings/rdc/imx_rdc.h>
16
17 /* OSC/PLL is already initialized by ROM and Cortex-A53 (u-boot) */
SOC_RdcInit(void)18 static void SOC_RdcInit(void)
19 {
20 /* Move M7 core to specific RDC domain 1 */
21 rdc_domain_assignment_t assignment = {0};
22 uint8_t domainId = 0U;
23
24 domainId = RDC_GetCurrentMasterDomainId(RDC);
25 /* Only configure the RDC if RDC peripheral write access allowed. */
26 if ((0x1U & RDC_GetPeriphAccessPolicy(RDC, kRDC_Periph_RDC, domainId)) != 0U) {
27 assignment.domainId = M7_DOMAIN_ID;
28 RDC_SetMasterDomainAssignment(RDC, kRDC_Master_M7, &assignment);
29 }
30
31 /*
32 * The M7 core is running at domain 1, now enable the clock gate of the following IP/BUS/PLL
33 * in domain 1 in the CCM. In this way, to ensure the clock of the peripherals used by M
34 * core not be affected by A core which is running at domain 0.
35 */
36 CLOCK_EnableClock(kCLOCK_Iomux);
37
38 CLOCK_EnableClock(kCLOCK_Ipmux1);
39 CLOCK_EnableClock(kCLOCK_Ipmux2);
40 CLOCK_EnableClock(kCLOCK_Ipmux3);
41
42 #if defined(FLASH_TARGET)
43 CLOCK_EnableClock(kCLOCK_Qspi);
44 #endif
45
46 /* Enable the CCGR gate for SysPLL1 in Domain 1 */
47 CLOCK_ControlGate(kCLOCK_SysPll1Gate, kCLOCK_ClockNeededAll);
48 /* Enable the CCGR gate for SysPLL2 in Domain 1 */
49 CLOCK_ControlGate(kCLOCK_SysPll2Gate, kCLOCK_ClockNeededAll);
50 /* Enable the CCGR gate for SysPLL3 in Domain 1 */
51 CLOCK_ControlGate(kCLOCK_SysPll3Gate, kCLOCK_ClockNeededAll);
52 #ifdef CONFIG_INIT_VIDEO_PLL
53 /* Enable the CCGR gate for VideoPLL1 in Domain 1 */
54 CLOCK_ControlGate(kCLOCK_VideoPll1Gate, kCLOCK_ClockNeededAll);
55 #endif
56 }
57
58 /* Integer PLLs: Fout = (mainDiv * refSel) / (preDiv * 2^ postDiv) */
59 /* SYSTEM PLL1 configuration */
60 const ccm_analog_integer_pll_config_t g_sysPll1Config = {
61 .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */
62 .mainDiv = 400U,
63 .preDiv = 3U,
64 .postDiv = 2U, /*!< SYSTEM PLL1 frequency = 800MHZ */
65 };
66
67 /* SYSTEM PLL2 configuration */
68 const ccm_analog_integer_pll_config_t g_sysPll2Config = {
69 .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */
70 .mainDiv = 250U,
71 .preDiv = 3U,
72 .postDiv = 1U, /*!< SYSTEM PLL2 frequency = 1000MHZ */
73 };
74
75 /* SYSTEM PLL3 configuration */
76 const ccm_analog_integer_pll_config_t g_sysPll3Config = {
77 .refSel = kANALOG_PllRefOsc24M, /*!< PLL reference OSC24M */
78 .mainDiv = 300,
79 .preDiv = 3U,
80 .postDiv = 2U, /*!< SYSTEM PLL3 frequency = 600MHZ */
81 };
82
SOC_ClockInit(void)83 static void SOC_ClockInit(void)
84 {
85 /*
86 * The following steps just show how to configure the PLL clock sources using the clock
87 * driver on M7 core side . Please note that the ROM has already configured the SYSTEM PLL1
88 * to 800Mhz when power up the SOC, meanwhile A core would enable SYSTEM PLL1, SYSTEM PLL2
89 * and SYSTEM PLL3 by U-Boot. Therefore, there is no need to configure the system PLL again
90 * on M7 side, otherwise it would have a risk to make the SOC hang.
91 */
92
93 /* switch AHB NOC root to 24M first in order to configure the SYSTEM PLL1. */
94 CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxOsc24M);
95
96 /* switch AXI M7 root to 24M first in order to configure the SYSTEM PLL2. */
97 CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M);
98
99 /* Set root clock to 800M */
100 CLOCK_SetRootDivider(kCLOCK_RootM7, 1U, 1U);
101 /* switch cortex-m7 to SYSTEM PLL1 */
102 CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll1);
103
104 /* Set root clock freq to 133M / 1= 133MHZ */
105 CLOCK_SetRootDivider(kCLOCK_RootAhb, 1U, 1U);
106 /* switch AHB to SYSTEM PLL1 DIV6 */
107 CLOCK_SetRootMux(kCLOCK_RootAhb, kCLOCK_AhbRootmuxSysPll1Div6);
108
109 #if defined(CONFIG_UART_MCUX_IUART)
110 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1))
111 /* Set UART source to SysPLL1 Div10 80MHZ */
112 CLOCK_SetRootMux(kCLOCK_RootUart1, kCLOCK_UartRootmuxSysPll1Div10);
113 /* Set root clock to 80MHZ/ 1= 80MHZ */
114 CLOCK_SetRootDivider(kCLOCK_RootUart1, 1U, 1U);
115 #endif
116 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2))
117 /* Set UART source to SysPLL1 Div10 80MHZ */
118 CLOCK_SetRootMux(kCLOCK_RootUart2, kCLOCK_UartRootmuxSysPll1Div10);
119 /* Set root clock to 80MHZ/ 1= 80MHZ */
120 CLOCK_SetRootDivider(kCLOCK_RootUart2, 1U, 1U);
121 #endif
122 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3))
123 /* Set UART source to SysPLL1 Div10 80MHZ */
124 CLOCK_SetRootMux(kCLOCK_RootUart3, kCLOCK_UartRootmuxSysPll1Div10);
125 /* Set root clock to 80MHZ/ 1= 80MHZ */
126 CLOCK_SetRootDivider(kCLOCK_RootUart3, 1U, 1U);
127 #endif
128 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
129 /* Set UART source to SysPLL1 Div10 80MHZ */
130 CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxSysPll1Div10);
131 /* Set root clock to 80MHZ/ 1= 80MHZ */
132 CLOCK_SetRootDivider(kCLOCK_RootUart4, 1U, 1U);
133 #endif
134 #endif
135
136 #if defined(CONFIG_SPI_MCUX_ECSPI)
137 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ecspi1))
138 /* Set ECSPI1 source to SYSTEM PLL1 800MHZ */
139 CLOCK_SetRootMux(kCLOCK_RootEcspi1, kCLOCK_EcspiRootmuxSysPll1);
140 /* Set root clock to 800MHZ / 10 = 80MHZ */
141 CLOCK_SetRootDivider(kCLOCK_RootEcspi1, 2U, 5U);
142 #endif
143
144 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ecspi2))
145 /* Set ECSPI2 source to SYSTEM PLL1 800MHZ */
146 CLOCK_SetRootMux(kCLOCK_RootEcspi2, kCLOCK_EcspiRootmuxSysPll1);
147 /* Set root clock to 800MHZ / 10 = 80MHZ */
148 CLOCK_SetRootDivider(kCLOCK_RootEcspi2, 2U, 5U);
149 #endif
150
151 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ecspi3))
152 /* Set ECSPI3 source to SYSTEM PLL1 800MHZ */
153 CLOCK_SetRootMux(kCLOCK_RootEcspi3, kCLOCK_EcspiRootmuxSysPll1);
154 /* Set root clock to 800MHZ / 10 = 80MHZ */
155 CLOCK_SetRootDivider(kCLOCK_RootEcspi3, 2U, 5U);
156 #endif
157 #endif
158
159 CLOCK_EnableClock(kCLOCK_Rdc); /* Enable RDC clock */
160 CLOCK_EnableClock(kCLOCK_Ocram); /* Enable Ocram clock */
161
162 /* The purpose to enable the following modules clock is to make sure the M7 core could work
163 * normally when A53 core enters the low power status.
164 */
165 CLOCK_EnableClock(kCLOCK_Sim_m);
166 CLOCK_EnableClock(kCLOCK_Sim_main);
167 CLOCK_EnableClock(kCLOCK_Sim_s);
168 CLOCK_EnableClock(kCLOCK_Sim_wakeup);
169 CLOCK_EnableClock(kCLOCK_Debug);
170 CLOCK_EnableClock(kCLOCK_Dram);
171 CLOCK_EnableClock(kCLOCK_Sec_Debug);
172 }
173
gpio_init(void)174 static void gpio_init(void)
175 {
176
177 #if defined(CONFIG_GPIO_MCUX_IGPIO)
178 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio1))
179
180 CLOCK_EnableClock(kCLOCK_Gpio1);
181
182 #endif
183 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio2))
184
185 CLOCK_EnableClock(kCLOCK_Gpio2);
186
187 #endif
188 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio3))
189
190 CLOCK_EnableClock(kCLOCK_Gpio3);
191
192 #endif
193 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio4))
194
195 CLOCK_EnableClock(kCLOCK_Gpio4);
196
197 #endif
198 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gpio5))
199
200 CLOCK_EnableClock(kCLOCK_Gpio5);
201
202 #endif
203 #endif
204 }
205
soc_early_init_hook(void)206 void soc_early_init_hook(void)
207 {
208
209 /* SoC specific RDC settings */
210 SOC_RdcInit();
211
212 /* SoC specific Clock settings */
213 SOC_ClockInit();
214
215 gpio_init();
216 }
217