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