1 /*
2 ** ###################################################################
3 **     Processors:          MIMX8MN2CVTIZ
4 **                          MIMX8MN2DVTJZ
5 **
6 **     Compilers:           GNU C Compiler
7 **                          IAR ANSI C/C++ Compiler for ARM
8 **                          Keil ARM C/C++ Compiler
9 **
10 **     Reference manual:    MX8MNRM, Rev.B, 07/2019
11 **     Version:             rev. 2.0, 2019-09-23
12 **     Build:               b211101
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-2021 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 (2019-04-22)
30 **         Initial version.
31 **     - rev. 2.0 (2019-09-23)
32 **         Rev.B Header RFP
33 **
34 ** ###################################################################
35 */
36 
37 /*!
38  * @file MIMX8MN2_cm7
39  * @version 2.0
40  * @date 011121
41  * @brief Device specific configuration file for MIMX8MN2 (implementation file)
42  *
43  * Provides a system configuration function and a global variable that contains
44  * the system frequency. It configures the device and initializes the oscillator
45  * (PLL) that is part of the microcontroller device.
46  */
47 
48 #include <stdint.h>
49 #include "fsl_device_registers.h"
50 
51 /*!
52  * @brief CCM reg macros to extract corresponding registers bit field.
53  */
54 #define CCM_BIT_FIELD_VAL(val, mask, shift) (((val)&mask) >> shift)
55 
56 /*!
57  * @brief CCM reg macros to get corresponding registers values.
58  */
59 #define CCM_ANALOG_REG_VAL(base, off) (*((volatile uint32_t *)((uint32_t)(base) + (off))))
60 
61 /*******************************************************************************
62  * Prototypes
63  ******************************************************************************/
64 uint32_t GetFracPllFreq(const volatile uint32_t *base);
65 uint32_t GetIntegerPllFreq(const volatile uint32_t *base);
66 
GetFracPllFreq(const volatile uint32_t * base)67 uint32_t GetFracPllFreq(const volatile uint32_t *base)
68 {
69     uint32_t fracCfg0   = CCM_ANALOG_REG_VAL(base, 0U);
70     uint32_t fracCfg1   = CCM_ANALOG_REG_VAL(base, 4U);
71     uint32_t fracCfg2   = CCM_ANALOG_REG_VAL(base, 8U);
72     uint32_t refClkFreq = 0U;
73     uint64_t fracClk    = 0U;
74 
75     uint8_t refSel   = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg0, CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK,
76                                                 CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_SHIFT);
77     uint32_t mainDiv = CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
78                                          CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
79     uint8_t preDiv   = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
80                                                 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
81     uint8_t postDiv  = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
82                                                  CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
83     uint32_t dsm     = CCM_BIT_FIELD_VAL(fracCfg2, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_MASK,
84                                      CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_SHIFT);
85 
86     if (refSel == 0U) /* OSC 24M Clock */
87     {
88         refClkFreq = CPU_XTAL_SOSC_CLK_24MHZ;
89     }
90     else
91     {
92         refClkFreq = CLK_PAD_CLK; /* CLK_PAD_CLK Clock, please note that the value is 0hz by default, it could be set at
93                                      system_MIMX8MNx_cm7.h :96 */
94     }
95     fracClk = (uint64_t)refClkFreq * ((uint64_t)mainDiv * 65536UL + (uint64_t)dsm) /
96               ((uint64_t)65536UL * preDiv * (1UL << postDiv));
97 
98     return (uint32_t)fracClk;
99 }
100 
GetIntegerPllFreq(const volatile uint32_t * base)101 uint32_t GetIntegerPllFreq(const volatile uint32_t *base)
102 {
103     uint32_t integerCfg0 = CCM_ANALOG_REG_VAL(base, 0U);
104     uint32_t integerCfg1 = CCM_ANALOG_REG_VAL(base, 4U);
105     uint32_t refClkFreq  = 0U;
106     uint64_t pllOutClock = 0U;
107 
108     uint8_t pllBypass = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg0, CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_BYPASS_MASK,
109                                                    CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_BYPASS_SHIFT);
110     uint8_t refSel    = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg0, CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK,
111                                                 CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_SHIFT);
112     uint32_t mainDiv  = CCM_BIT_FIELD_VAL(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
113                                          CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
114     uint8_t preDiv    = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
115                                                 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
116     uint8_t postDiv   = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
117                                                  CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
118 
119     if (refSel == 0U) /* OSC 24M Clock */
120     {
121         refClkFreq = CPU_XTAL_SOSC_CLK_24MHZ;
122     }
123     else
124     {
125         refClkFreq = CLK_PAD_CLK; /* CLK_PAD_CLK Clock, please note that the value is 0hz by default, it could be set at
126                                      system_MIMX8MNx_cm7.h :96 */
127     }
128 
129     if (pllBypass != 0U)
130     {
131         pllOutClock = refClkFreq;
132     }
133 
134     else
135     {
136         pllOutClock = (uint64_t)refClkFreq * mainDiv / (((uint64_t)(1U) << postDiv) * preDiv);
137     }
138 
139     return (uint32_t)pllOutClock;
140 }
141 
142 /* ----------------------------------------------------------------------------
143    -- Core clock
144    ---------------------------------------------------------------------------- */
145 
146 uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
147 
148 /* ----------------------------------------------------------------------------
149    -- SystemInit()
150    ---------------------------------------------------------------------------- */
151 
SystemInit(void)152 void SystemInit(void)
153 {
154 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
155     SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access */
156 #endif                                                 /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
157 
158     SystemInitHook();
159 }
160 
161 /* ----------------------------------------------------------------------------
162    -- SystemCoreClockUpdate()
163    ---------------------------------------------------------------------------- */
164 
SystemCoreClockUpdate(void)165 void SystemCoreClockUpdate(void)
166 {
167     volatile uint32_t *M7_ClockRoot = (volatile uint32_t *)(&(CCM)->ROOT[1].TARGET_ROOT);
168     uint32_t pre  = ((*M7_ClockRoot & CCM_TARGET_ROOT_PRE_PODF_MASK) >> CCM_TARGET_ROOT_PRE_PODF_SHIFT) + 1U;
169     uint32_t post = ((*M7_ClockRoot & CCM_TARGET_ROOT_POST_PODF_MASK) >> CCM_TARGET_ROOT_POST_PODF_SHIFT) + 1U;
170 
171     uint32_t freq = 0U;
172 
173     switch ((*M7_ClockRoot & CCM_TARGET_ROOT_MUX_MASK) >> CCM_TARGET_ROOT_MUX_SHIFT)
174     {
175         case 0U: /* OSC 24M Clock */
176             freq = CPU_XTAL_SOSC_CLK_24MHZ;
177             break;
178         case 1U:                                                             /* System PLL2 DIV5 */
179             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL2_GEN_CTRL)) / 5U; /* Get System PLL2 DIV5 freq */
180             break;
181         case 2U:                                                             /* System PLL2 DIV4 */
182             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL2_GEN_CTRL)) / 4U; /* Get System PLL2 DIV4 freq */
183             break;
184         case 3U:                                                             /* System PLL1 DIV3 */
185             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL1_GEN_CTRL)) / 3U; /* Get System PLL1 DIV3 freq */
186             break;
187         case 4U:                                                        /* System PLL1 */
188             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL1_GEN_CTRL)); /* Get System PLL1 freq */
189             break;
190         case 5U:                                                       /* AUDIO PLL1 */
191             freq = GetFracPllFreq(&(CCM_ANALOG->AUDIO_PLL1_GEN_CTRL)); /* Get AUDIO PLL1 freq */
192             break;
193         case 6U:                                                       /* VIDEO PLL1 */
194             freq = GetFracPllFreq(&(CCM_ANALOG->VIDEO_PLL1_GEN_CTRL)); /* Get VIDEO PLL1 freq */
195             break;
196         case 7U:                                                        /* System PLL3 */
197             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL3_GEN_CTRL)); /* Get System PLL3 freq */
198             break;
199         default:
200             freq = CPU_XTAL_SOSC_CLK_24MHZ;
201             break;
202     }
203 
204     SystemCoreClock = freq / pre / post;
205 }
206 
207 /* ----------------------------------------------------------------------------
208    -- SystemInitHook()
209    ---------------------------------------------------------------------------- */
210 
SystemInitHook(void)211 __attribute__((weak)) void SystemInitHook(void)
212 {
213     /* Void implementation of the weak function. */
214 }
215