1 /*
2 ** ###################################################################
3 ** Processors: MIMX8MQ5CVAHZ
4 ** MIMX8MQ5DVAJZ
5 **
6 ** Compilers: Keil ARM C/C++ Compiler
7 ** GNU C Compiler
8 ** IAR ANSI C/C++ Compiler for ARM
9 **
10 ** Reference manual: IMX8MDQLQRM, Rev. 0, Jan. 2018
11 ** Version: rev. 4.0, 2018-01-26
12 ** Build: b180903
13 **
14 ** Abstract:
15 ** Provides a system configuration function and a global variable that
16 ** contains the system frequency. It configures the device and initializes
17 ** the oscillator (PLL) that is part of the microcontroller device.
18 **
19 ** Copyright 2016 Freescale Semiconductor, Inc.
20 ** Copyright 2016-2018 NXP
21 ** All rights reserved.
22 **
23 ** SPDX-License-Identifier: BSD-3-Clause
24 **
25 ** http: www.nxp.com
26 ** mail: support@nxp.com
27 **
28 ** Revisions:
29 ** - rev. 1.0 (2017-01-10)
30 ** Initial version.
31 ** - rev. 2.0 (2017-04-27)
32 ** Rev.B Header EAR1
33 ** - rev. 3.0 (2017-07-19)
34 ** Rev.C Header EAR2
35 ** - rev. 4.0 (2018-01-26)
36 ** Rev.D Header RFP
37 **
38 ** ###################################################################
39 */
40
41 /*!
42 * @file MIMX8MQ5_cm4
43 * @version 4.0
44 * @date 2018-01-26
45 * @brief Device specific configuration file for MIMX8MQ5_cm4 (implementation
46 * file)
47 *
48 * Provides a system configuration function and a global variable that contains
49 * the system frequency. It configures the device and initializes the oscillator
50 * (PLL) that is part of the microcontroller device.
51 */
52
53 #include <stdint.h>
54 #include "fsl_device_registers.h"
55
56 /*!
57 * @brief CCM reg macros to extract corresponding registers bit field.
58 */
59 #define CCM_BIT_FIELD_VAL(val, mask, shift) (((val)&mask) >> shift)
60
61 /*!
62 * @brief CCM reg macros to get corresponding registers values.
63 */
64 #define CCM_ANALOG_REG_VAL(base, off) (*((volatile uint32_t *)((uint32_t)(base) + (off))))
65
66 /*******************************************************************************
67 * Prototypes
68 ******************************************************************************/
69 uint32_t GetFracPllFreq(const volatile uint32_t *base);
70 uint32_t GetSSCGPllFreq(const volatile uint32_t *base);
71
GetFracPllFreq(const volatile uint32_t * base)72 uint32_t GetFracPllFreq(const volatile uint32_t *base)
73 {
74 uint32_t fracCfg0 = CCM_ANALOG_REG_VAL(base, 0U);
75 uint32_t fracCfg1 = CCM_ANALOG_REG_VAL(base, 4U);
76 uint32_t refClkFreq = 0U;
77 uint64_t fracClk = 0U;
78
79 uint8_t refSel = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg0, CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_SEL_MASK,
80 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_SEL_SHIFT);
81 uint8_t refDiv = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg0, CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_DIV_VAL_MASK,
82 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_REFCLK_DIV_VAL_SHIFT);
83 uint8_t outDiv = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg0, CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_OUTPUT_DIV_VAL_MASK,
84 CCM_ANALOG_AUDIO_PLL1_CFG0_PLL_OUTPUT_DIV_VAL_SHIFT);
85 uint32_t fracDiv = CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_FRAC_DIV_CTL_MASK,
86 CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_FRAC_DIV_CTL_SHIFT);
87 uint8_t intDiv = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_INT_DIV_CTL_MASK,
88 CCM_ANALOG_AUDIO_PLL1_CFG1_PLL_INT_DIV_CTL_SHIFT);
89
90 if (refSel == 0U) /* OSC 25M Clock */
91 {
92 refClkFreq = CPU_XTAL_SOSC_CLK_25MHZ;
93 }
94 else if ((refSel == 1U) || /* OSC 27M Clock */
95 (refSel == 2U)) /* HDMI_PYH 27M Clock */
96 {
97 refClkFreq = CPU_XTAL_SOSC_CLK_27MHZ;
98 }
99 else
100 {
101 refClkFreq = CLK_P_N_FREQ; /* CLK_P_N Clock, please note that the value is 0hz by default, it could be set at
102 system_MIMX8MQx_cm4.h :88 */
103 }
104 refClkFreq /= (uint32_t)refDiv + 1U;
105 fracClk = (uint64_t)refClkFreq * 8U * (1U + intDiv) + (((uint64_t)refClkFreq * 8U * fracDiv) >> 24U);
106
107 return (uint32_t)(fracClk / (((uint64_t)outDiv + 1U) * 2U));
108 }
109
GetSSCGPllFreq(const volatile uint32_t * base)110 uint32_t GetSSCGPllFreq(const volatile uint32_t *base)
111 {
112 uint32_t sscgCfg0 = CCM_ANALOG_REG_VAL(base, 0U);
113 uint32_t sscgCfg1 = CCM_ANALOG_REG_VAL(base, 4U);
114 uint32_t sscgCfg2 = CCM_ANALOG_REG_VAL(base, 8U);
115 uint32_t refClkFreq = 0U;
116 uint64_t pll2InputClock = 0U;
117
118 uint8_t pll1Bypass = (uint8_t)CCM_BIT_FIELD_VAL(sscgCfg0, CCM_ANALOG_SYS_PLL1_CFG0_PLL_BYPASS1_MASK,
119 CCM_ANALOG_SYS_PLL1_CFG0_PLL_BYPASS1_SHIFT);
120 uint8_t refSel = (uint8_t)CCM_BIT_FIELD_VAL(sscgCfg0, CCM_ANALOG_SYS_PLL1_CFG0_PLL_REFCLK_SEL_MASK,
121 CCM_ANALOG_SYS_PLL1_CFG0_PLL_REFCLK_SEL_SHIFT);
122 uint8_t refDiv1 = (uint8_t)CCM_BIT_FIELD_VAL(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR1_MASK,
123 CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR1_SHIFT) +
124 1U;
125 uint8_t refDiv2 = (uint8_t)CCM_BIT_FIELD_VAL(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR2_MASK,
126 CCM_ANALOG_SYS_PLL1_CFG2_PLL_REF_DIVR2_SHIFT) +
127 1U;
128 uint8_t divf1 = (uint8_t)CCM_BIT_FIELD_VAL(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF1_MASK,
129 CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF1_SHIFT) +
130 1U;
131 uint8_t divf2 = (uint8_t)CCM_BIT_FIELD_VAL(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF2_MASK,
132 CCM_ANALOG_SYS_PLL1_CFG2_PLL_FEEDBACK_DIVF2_SHIFT) +
133 1U;
134 uint8_t outDiv = (uint8_t)CCM_BIT_FIELD_VAL(sscgCfg2, CCM_ANALOG_SYS_PLL1_CFG2_PLL_OUTPUT_DIV_VAL_MASK,
135 CCM_ANALOG_SYS_PLL1_CFG2_PLL_OUTPUT_DIV_VAL_SHIFT) +
136 1U;
137
138 if (refSel == 0U) /* OSC 25M Clock */
139 {
140 refClkFreq = CPU_XTAL_SOSC_CLK_25MHZ;
141 }
142 else if ((refSel == 1U) || /* OSC 27M Clock */
143 (refSel == 2U)) /* HDMI_PYH 27M Clock */
144 {
145 refClkFreq = CPU_XTAL_SOSC_CLK_27MHZ;
146 }
147 else
148 {
149 refClkFreq = CLK_P_N_FREQ; /* CLK_P_N Clock, please note that the value is 0hz by default, it could be set at
150 system_MIMX8MQx_cm4.h :88 */
151 }
152
153 refClkFreq /= refDiv1;
154
155 if (pll1Bypass != 0U)
156 {
157 pll2InputClock = refClkFreq;
158 }
159 else if ((sscgCfg1 & CCM_ANALOG_SYS_PLL1_CFG1_PLL_SSE_MASK) != 0U)
160 {
161 pll2InputClock = (uint64_t)refClkFreq * 8U * divf1 / refDiv2;
162 }
163 else
164 {
165 pll2InputClock = (uint64_t)refClkFreq * 2U * divf1 / refDiv2;
166 }
167
168 return (uint32_t)(pll2InputClock * divf2 / outDiv);
169 }
170
171 /* ----------------------------------------------------------------------------
172 -- Core clock
173 ---------------------------------------------------------------------------- */
174
175 uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
176
177 /* ----------------------------------------------------------------------------
178 -- SystemInit()
179 ---------------------------------------------------------------------------- */
180
SystemInit(void)181 void SystemInit(void)
182 {
183 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
184 SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access */
185 #endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
186
187 /* Initialize Cache */
188 /* Enable Code Bus Cache */
189 /* set command to invalidate all ways, and write GO bit to initiate command */
190 LMEM->PCCCR |= LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_INVW0_MASK;
191 LMEM->PCCCR |= LMEM_PCCCR_GO_MASK;
192 /* Wait until the command completes */
193 while ((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) != 0U)
194 {
195 }
196 /* Enable cache, enable write buffer */
197 LMEM->PCCCR |= (LMEM_PCCCR_ENWRBUF_MASK | LMEM_PCCCR_ENCACHE_MASK);
198
199 /* Enable System Bus Cache */
200 /* set command to invalidate all ways, and write GO bit to initiate command */
201 LMEM->PSCCR |= LMEM_PSCCR_INVW1_MASK | LMEM_PSCCR_INVW0_MASK;
202 LMEM->PSCCR |= LMEM_PSCCR_GO_MASK;
203 /* Wait until the command completes */
204 while ((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) != 0U)
205 {
206 }
207 /* Enable cache, enable write buffer */
208 LMEM->PSCCR |= (LMEM_PSCCR_ENWRBUF_MASK | LMEM_PSCCR_ENCACHE_MASK);
209
210 __ISB();
211 __DSB();
212
213 SystemInitHook();
214 }
215
216 /* ----------------------------------------------------------------------------
217 -- SystemCoreClockUpdate()
218 ---------------------------------------------------------------------------- */
219
SystemCoreClockUpdate(void)220 void SystemCoreClockUpdate(void)
221 {
222 volatile uint32_t *M4_ClockRoot = (volatile uint32_t *)(&(CCM)->ROOT[1].TARGET_ROOT);
223 uint32_t pre = ((*M4_ClockRoot & CCM_TARGET_ROOT_PRE_PODF_MASK) >> CCM_TARGET_ROOT_PRE_PODF_SHIFT) + 1U;
224 uint32_t post = ((*M4_ClockRoot & CCM_TARGET_ROOT_POST_PODF_MASK) >> CCM_TARGET_ROOT_POST_PODF_SHIFT) + 1U;
225
226 uint32_t freq = 0U;
227
228 switch ((*M4_ClockRoot & CCM_TARGET_ROOT_MUX_MASK) >> CCM_TARGET_ROOT_MUX_SHIFT)
229 {
230 case 0U: /* OSC 25M Clock */
231 freq = CPU_XTAL_SOSC_CLK_25MHZ;
232 break;
233 case 1U: /* System PLL2 DIV5 */
234 freq = GetSSCGPllFreq(&(CCM_ANALOG->SYS_PLL2_CFG0)) / 5U; /* Get System PLL2 DIV5 freq */
235 break;
236 case 2U: /* System PLL2 DIV4 */
237 freq = GetSSCGPllFreq(&(CCM_ANALOG->SYS_PLL2_CFG0)) / 4U; /* Get System PLL2 DIV4 freq */
238 break;
239 case 3U: /* System PLL1 DIV3 */
240 freq = GetSSCGPllFreq(&(CCM_ANALOG->SYS_PLL1_CFG0)) / 3U; /* Get System PLL1 DIV3 freq */
241 break;
242 case 4U: /* System PLL1 */
243 freq = GetSSCGPllFreq(&(CCM_ANALOG->SYS_PLL1_CFG0)); /* Get System PLL1 freq */
244 break;
245 case 5U: /* AUDIO PLL1 */
246 freq = GetFracPllFreq(&(CCM_ANALOG->AUDIO_PLL1_CFG0)); /* Get AUDIO PLL1 freq */
247 break;
248 case 6U: /* VIDEO PLL1 */
249 freq = GetFracPllFreq(&(CCM_ANALOG->VIDEO_PLL1_CFG0)); /* Get VIDEO PLL1 freq */
250 break;
251 case 7U: /* System PLL3 */
252 freq = GetSSCGPllFreq(&(CCM_ANALOG->SYS_PLL3_CFG0)); /* Get System PLL3 freq */
253 break;
254 default:
255 freq = CPU_XTAL_SOSC_CLK_25MHZ;
256 break;
257 }
258
259 SystemCoreClock = freq / pre / post;
260 }
261
262 /* ----------------------------------------------------------------------------
263 -- SystemInitHook()
264 ---------------------------------------------------------------------------- */
265
SystemInitHook(void)266 __attribute__((weak)) void SystemInitHook(void)
267 {
268 /* Void implementation of the weak function. */
269 }
270