1 /*
2 ** ###################################################################
3 **     Processors:          MIMX8MM4CVTKZ
4 **                          MIMX8MM4DVTLZ
5 **
6 **     Compilers:           GNU C Compiler
7 **                          IAR ANSI C/C++ Compiler for ARM
8 **                          Keil ARM C/C++ Compiler
9 **
10 **     Reference manual:    MX8MMRM, Rev. 0, 02/2019
11 **     Version:             rev. 4.0, 2019-02-18
12 **     Build:               b190228
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-2019 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 (2018-03-26)
30 **         Initial version.
31 **     - rev. 2.0 (2018-07-20)
32 **         Rev.A Header EAR
33 **     - rev. 3.0 (2018-10-24)
34 **         Rev.B Header PRC
35 **     - rev. 4.0 (2019-02-18)
36 **         Rev.0 Header RFP
37 **
38 ** ###################################################################
39 */
40 
41 /*!
42  * @file MIMX8MM4_cm4
43  * @version 4.0
44  * @date 2019-02-18
45  * @brief Device specific configuration file for MIMX8MM4_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 GetIntegerPllFreq(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 fracCfg2   = CCM_ANALOG_REG_VAL(base, 8U);
77     uint32_t refClkFreq = 0U;
78     uint64_t fracClk    = 0U;
79 
80     uint8_t refSel   = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg0, CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK,
81                                                 CCM_ANALOG_AUDIO_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_SHIFT);
82     uint32_t mainDiv = CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
83                                          CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
84     uint8_t preDiv   = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
85                                                 CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
86     uint8_t postDiv  = (uint8_t)CCM_BIT_FIELD_VAL(fracCfg1, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
87                                                  CCM_ANALOG_AUDIO_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
88     uint32_t dsm     = CCM_BIT_FIELD_VAL(fracCfg2, CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_MASK,
89                                      CCM_ANALOG_AUDIO_PLL1_FDIV_CTL1_PLL_DSM_SHIFT);
90 
91     if (refSel == 0U) /* OSC 24M Clock */
92     {
93         refClkFreq = CPU_XTAL_SOSC_CLK_24MHZ;
94     }
95     else
96     {
97         refClkFreq = CLK_PAD_CLK; /* CLK_PAD_CLK Clock, please note that the value is 0hz by default, it could be set at
98                                      system_MIMX8MMx_cm4.h :96 */
99     }
100     fracClk = (uint64_t)refClkFreq * ((uint64_t)mainDiv * 65536UL + (uint64_t)dsm) /
101               ((uint64_t)65536UL * preDiv * (1UL << postDiv));
102 
103     return (uint32_t)fracClk;
104 }
105 
GetIntegerPllFreq(const volatile uint32_t * base)106 uint32_t GetIntegerPllFreq(const volatile uint32_t *base)
107 {
108     uint32_t integerCfg0 = CCM_ANALOG_REG_VAL(base, 0U);
109     uint32_t integerCfg1 = CCM_ANALOG_REG_VAL(base, 4U);
110     uint32_t refClkFreq  = 0U;
111     uint64_t pllOutClock = 0U;
112 
113     uint8_t pllBypass = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg0, CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_BYPASS_MASK,
114                                                    CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_BYPASS_SHIFT);
115     uint8_t refSel    = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg0, CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_MASK,
116                                                 CCM_ANALOG_SYS_PLL1_GEN_CTRL_PLL_REF_CLK_SEL_SHIFT);
117     uint32_t mainDiv  = CCM_BIT_FIELD_VAL(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_MASK,
118                                          CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_MAIN_DIV_SHIFT);
119     uint8_t preDiv    = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_MASK,
120                                                 CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_PRE_DIV_SHIFT);
121     uint8_t postDiv   = (uint8_t)CCM_BIT_FIELD_VAL(integerCfg1, CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_MASK,
122                                                  CCM_ANALOG_SYS_PLL1_FDIV_CTL0_PLL_POST_DIV_SHIFT);
123 
124     if (refSel == 0U) /* OSC 24M Clock */
125     {
126         refClkFreq = CPU_XTAL_SOSC_CLK_24MHZ;
127     }
128     else
129     {
130         refClkFreq = CLK_PAD_CLK; /* CLK_PAD_CLK Clock, please note that the value is 0hz by default, it could be set at
131                                      system_MIMX8MMx_cm4.h :96 */
132     }
133 
134     if (pllBypass != 0U)
135     {
136         pllOutClock = refClkFreq;
137     }
138 
139     else
140     {
141         pllOutClock = (uint64_t)refClkFreq * mainDiv / (((uint64_t)(1U) << postDiv) * preDiv);
142     }
143 
144     return (uint32_t)pllOutClock;
145 }
146 
147 /* ----------------------------------------------------------------------------
148    -- Core clock
149    ---------------------------------------------------------------------------- */
150 
151 uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
152 
153 /* ----------------------------------------------------------------------------
154    -- SystemInit()
155    ---------------------------------------------------------------------------- */
156 
SystemInit(void)157 void SystemInit(void)
158 {
159 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
160     SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access */
161 #endif                                                 /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
162 
163     /* Initialize Cache */
164     /* Enable Code Bus Cache */
165     /* set command to invalidate all ways, and write GO bit to initiate command */
166     LMEM->PCCCR |= LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_INVW0_MASK;
167     LMEM->PCCCR |= LMEM_PCCCR_GO_MASK;
168     /* Wait until the command completes */
169     while ((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) != 0U)
170     {
171     }
172     /* Enable cache, enable write buffer */
173     LMEM->PCCCR |= (LMEM_PCCCR_ENWRBUF_MASK | LMEM_PCCCR_ENCACHE_MASK);
174 
175     /* Enable System Bus Cache */
176     /* set command to invalidate all ways, and write GO bit to initiate command */
177     LMEM->PSCCR |= LMEM_PSCCR_INVW1_MASK | LMEM_PSCCR_INVW0_MASK;
178     LMEM->PSCCR |= LMEM_PSCCR_GO_MASK;
179     /* Wait until the command completes */
180     while ((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) != 0U)
181     {
182     }
183     /* Enable cache, enable write buffer */
184     LMEM->PSCCR |= (LMEM_PSCCR_ENWRBUF_MASK | LMEM_PSCCR_ENCACHE_MASK);
185 
186     __ISB();
187     __DSB();
188 
189     SystemInitHook();
190 }
191 
192 /* ----------------------------------------------------------------------------
193    -- SystemCoreClockUpdate()
194    ---------------------------------------------------------------------------- */
195 
SystemCoreClockUpdate(void)196 void SystemCoreClockUpdate(void)
197 {
198     volatile uint32_t *M4_ClockRoot = (volatile uint32_t *)(&(CCM)->ROOT[1].TARGET_ROOT);
199     uint32_t pre  = ((*M4_ClockRoot & CCM_TARGET_ROOT_PRE_PODF_MASK) >> CCM_TARGET_ROOT_PRE_PODF_SHIFT) + 1U;
200     uint32_t post = ((*M4_ClockRoot & CCM_TARGET_ROOT_POST_PODF_MASK) >> CCM_TARGET_ROOT_POST_PODF_SHIFT) + 1U;
201 
202     uint32_t freq = 0U;
203 
204     switch ((*M4_ClockRoot & CCM_TARGET_ROOT_MUX_MASK) >> CCM_TARGET_ROOT_MUX_SHIFT)
205     {
206         case 0U: /* OSC 24M Clock */
207             freq = CPU_XTAL_SOSC_CLK_24MHZ;
208             break;
209         case 1U:                                                             /* System PLL2 DIV5 */
210             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL2_GEN_CTRL)) / 5U; /* Get System PLL2 DIV5 freq */
211             break;
212         case 2U:                                                             /* System PLL2 DIV4 */
213             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL2_GEN_CTRL)) / 4U; /* Get System PLL2 DIV4 freq */
214             break;
215         case 3U:                                                             /* System PLL1 DIV3 */
216             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL1_GEN_CTRL)) / 3U; /* Get System PLL1 DIV3 freq */
217             break;
218         case 4U:                                                        /* System PLL1 */
219             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL1_GEN_CTRL)); /* Get System PLL1 freq */
220             break;
221         case 5U:                                                       /* AUDIO PLL1 */
222             freq = GetFracPllFreq(&(CCM_ANALOG->AUDIO_PLL1_GEN_CTRL)); /* Get AUDIO PLL1 freq */
223             break;
224         case 6U:                                                       /* VIDEO PLL1 */
225             freq = GetFracPllFreq(&(CCM_ANALOG->VIDEO_PLL1_GEN_CTRL)); /* Get VIDEO PLL1 freq */
226             break;
227         case 7U:                                                        /* System PLL3 */
228             freq = GetIntegerPllFreq(&(CCM_ANALOG->SYS_PLL3_GEN_CTRL)); /* Get System PLL3 freq */
229             break;
230         default:
231             freq = CPU_XTAL_SOSC_CLK_24MHZ;
232             break;
233     }
234 
235     SystemCoreClock = freq / pre / post;
236 }
237 
238 /* ----------------------------------------------------------------------------
239    -- SystemInitHook()
240    ---------------------------------------------------------------------------- */
241 
SystemInitHook(void)242 __attribute__((weak)) void SystemInitHook(void)
243 {
244     /* Void implementation of the weak function. */
245 }
246