1 /*
2 ** ###################################################################
3 **     Processors:          LPC55S26JBD100
4 **                          LPC55S26JBD64
5 **                          LPC55S26JEV98
6 **
7 **     Compilers:           GNU C Compiler
8 **                          IAR ANSI C/C++ Compiler for ARM
9 **                          Keil ARM C/C++ Compiler
10 **                          MCUXpresso Compiler
11 **
12 **     Reference manual:    LPC55S6x/LPC55S2x/LPC552x User manual(UM11126) Rev.1.3  16 May 2019
13 **     Version:             rev. 1.1, 2019-05-16
14 **     Build:               b220117
15 **
16 **     Abstract:
17 **         Provides a system configuration function and a global variable that
18 **         contains the system frequency. It configures the device and initializes
19 **         the oscillator (PLL) that is part of the microcontroller device.
20 **
21 **     Copyright 2016 Freescale Semiconductor, Inc.
22 **     Copyright 2016-2022 NXP
23 **     All rights reserved.
24 **
25 **     SPDX-License-Identifier: BSD-3-Clause
26 **
27 **     http:                 www.nxp.com
28 **     mail:                 support@nxp.com
29 **
30 **     Revisions:
31 **     - rev. 1.0 (2018-08-22)
32 **         Initial version based on v0.2UM
33 **     - rev. 1.1 (2019-05-16)
34 **         Initial A1 version based on v1.3UM
35 **
36 ** ###################################################################
37 */
38 
39 /*!
40  * @file LPC55S26
41  * @version 1.1
42  * @date 2019-05-16
43  * @brief Device specific configuration file for LPC55S26 (implementation file)
44  *
45  * Provides a system configuration function and a global variable that contains
46  * the system frequency. It configures the device and initializes the oscillator
47  * (PLL) that is part of the microcontroller device.
48  */
49 
50 #include <stdint.h>
51 #include "fsl_device_registers.h"
52 
53 /* PLL0 SSCG control1 */
54 #define PLL_SSCG_MD_FRACT_P 0U
55 #define PLL_SSCG_MD_INT_P 25U
56 #define PLL_SSCG_MD_FRACT_M (0x1FFFFFFUL << PLL_SSCG_MD_FRACT_P)
57 #define PLL_SSCG_MD_INT_M ((uint64_t)0xFFUL << PLL_SSCG_MD_INT_P)
58 
59 /* Get predivider (N) from PLL0 NDEC setting */
findPll0PreDiv(void)60 static uint32_t findPll0PreDiv(void)
61 {
62     uint32_t preDiv = 1UL;
63 
64     /* Direct input is not used? */
65     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPREDIV_MASK) == 0UL)
66     {
67         preDiv = SYSCON->PLL0NDEC & SYSCON_PLL0NDEC_NDIV_MASK;
68         if (preDiv == 0UL)
69         {
70             preDiv = 1UL;
71         }
72     }
73     return preDiv;
74 }
75 
76 /* Get postdivider (P) from PLL0 PDEC setting */
findPll0PostDiv(void)77 static uint32_t findPll0PostDiv(void)
78 {
79     uint32_t postDiv = 1;
80 
81     if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV_MASK) == 0UL)
82     {
83         if ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
84         {
85             postDiv = SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK;
86         }
87         else
88         {
89             postDiv = 2UL * (SYSCON->PLL0PDEC & SYSCON_PLL0PDEC_PDIV_MASK);
90         }
91         if (postDiv == 0UL)
92         {
93             postDiv = 2UL;
94         }
95     }
96     return postDiv;
97 }
98 
99 /* Get multiplier (M) from PLL0 SSCG and SEL_EXT settings */
findPll0MMult(void)100 static float findPll0MMult(void)
101 {
102     float mMult = 1.0F;
103     float mMult_fract;
104     uint32_t mMult_int;
105 
106     if ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_SEL_EXT_MASK) != 0UL)
107     {
108         mMult = (float)(uint32_t)((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MDIV_EXT_MASK) >> SYSCON_PLL0SSCG1_MDIV_EXT_SHIFT);
109     }
110     else
111     {
112         mMult_int   = ((SYSCON->PLL0SSCG1 & SYSCON_PLL0SSCG1_MD_MBS_MASK) << 7U);
113         mMult_int   = mMult_int | ((SYSCON->PLL0SSCG0) >> PLL_SSCG_MD_INT_P);
114         mMult_fract = ((float)(uint32_t)((SYSCON->PLL0SSCG0) & PLL_SSCG_MD_FRACT_M) /
115                        (float)(uint32_t)(1UL << PLL_SSCG_MD_INT_P));
116         mMult       = (float)mMult_int + mMult_fract;
117     }
118     if (0ULL == ((uint64_t)mMult))
119     {
120         mMult = 1.0F;
121     }
122     return mMult;
123 }
124 
125 /* Get predivider (N) from PLL1 NDEC setting */
findPll1PreDiv(void)126 static uint32_t findPll1PreDiv(void)
127 {
128     uint32_t preDiv = 1UL;
129 
130     /* Direct input is not used? */
131     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPREDIV_MASK) == 0UL)
132     {
133         preDiv = SYSCON->PLL1NDEC & SYSCON_PLL1NDEC_NDIV_MASK;
134         if (preDiv == 0UL)
135         {
136             preDiv = 1UL;
137         }
138     }
139     return preDiv;
140 }
141 
142 /* Get postdivider (P) from PLL1 PDEC setting */
findPll1PostDiv(void)143 static uint32_t findPll1PostDiv(void)
144 {
145     uint32_t postDiv = 1UL;
146 
147     if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV_MASK) == 0UL)
148     {
149         if ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPOSTDIV2_MASK) != 0UL)
150         {
151             postDiv = SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK;
152         }
153         else
154         {
155             postDiv = 2UL * (SYSCON->PLL1PDEC & SYSCON_PLL1PDEC_PDIV_MASK);
156         }
157         if (postDiv == 0UL)
158         {
159             postDiv = 2UL;
160         }
161     }
162     return postDiv;
163 }
164 
165 /* Get multiplier (M) from PLL1 MDEC settings */
findPll1MMult(void)166 static uint32_t findPll1MMult(void)
167 {
168     uint32_t mMult = 1UL;
169 
170     mMult = SYSCON->PLL1MDEC & SYSCON_PLL1MDEC_MDIV_MASK;
171 
172     if (mMult == 0UL)
173     {
174         mMult = 1UL;
175     }
176     return mMult;
177 }
178 
179 /* Get FRO 12M Clk */
180 /*! brief  Return Frequency of FRO 12MHz
181  *  return Frequency of FRO 12MHz
182  */
GetFro12MFreq(void)183 static uint32_t GetFro12MFreq(void)
184 {
185     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK) != 0UL) ? 12000000U : 0U;
186 }
187 
188 /* Get FRO 1M Clk */
189 /*! brief  Return Frequency of FRO 1MHz
190  *  return Frequency of FRO 1MHz
191  */
GetFro1MFreq(void)192 static uint32_t GetFro1MFreq(void)
193 {
194     return ((SYSCON->CLOCK_CTRL & SYSCON_CLOCK_CTRL_FRO1MHZ_CLK_ENA_MASK) != 0UL) ? 1000000U : 0U;
195 }
196 
197 /* Get EXT OSC Clk */
198 /*! brief  Return Frequency of External Clock
199  *  return Frequency of External Clock. If no external clock is used returns 0.
200  */
GetExtClkFreq(void)201 static uint32_t GetExtClkFreq(void)
202 {
203     return ((ANACTRL->XO32M_CTRL & ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK) != 0UL) ? CLK_CLK_IN : 0U;
204 }
205 
206 /* Get HF FRO Clk */
207 /*! brief  Return Frequency of High-Freq output of FRO
208  *  return Frequency of High-Freq output of FRO
209  */
GetFroHfFreq(void)210 static uint32_t GetFroHfFreq(void)
211 {
212     return ((ANACTRL->FRO192M_CTRL & ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK) != 0UL) ? 96000000U : 0U;
213 }
214 
215 /* Get RTC OSC Clk */
216 /*! brief  Return Frequency of 32kHz osc
217  *  return Frequency of 32kHz osc
218  */
GetOsc32KFreq(void)219 static uint32_t GetOsc32KFreq(void)
220 {
221     return ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_FRO32K_MASK)) && (0UL == (PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK))) ?
222                CLK_RTC_32K_CLK :
223                ((0UL == (PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_XTAL32K_MASK)) && ((PMC->RTCOSC32K & PMC_RTCOSC32K_SEL_MASK) != 0UL)) ?
224                CLK_RTC_32K_CLK :
225                0U;
226 }
227 
228 
229 
230 /* ----------------------------------------------------------------------------
231    -- Core clock
232    ---------------------------------------------------------------------------- */
233 
234 uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
235 
236 /* ----------------------------------------------------------------------------
237    -- SystemInit()
238    ---------------------------------------------------------------------------- */
239 
SystemInit(void)240 __attribute__ ((weak)) void SystemInit (void) {
241 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
242   SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2));    /* set CP10, CP11 Full Access in Secure mode */
243   #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
244   SCB_NS->CPACR |= ((3UL << 10*2) | (3UL << 11*2));    /* set CP10, CP11 Full Access in Non-secure mode */
245   #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
246 #endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
247 
248   SCB->CPACR |= ((3UL << 0*2) | (3UL << 1*2));    /* set CP0, CP1 Full Access in Secure mode (enable PowerQuad) */
249 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
250   SCB_NS->CPACR |= ((3UL << 0*2) | (3UL << 1*2));    /* set CP0, CP1 Full Access in Normal mode (enable PowerQuad) */
251 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
252 
253   SCB->NSACR |= ((3UL << 0) | (3UL << 10));   /* enable CP0, CP1, CP10, CP11 Non-secure Access */
254 
255 #if defined(__MCUXPRESSO)
256     extern void(*const g_pfnVectors[]) (void);
257     SCB->VTOR = (uint32_t) &g_pfnVectors;
258 #else
259     extern void *__Vectors;
260     SCB->VTOR = (uint32_t) &__Vectors;
261 #endif
262     SYSCON->TRACECLKDIV = 0;
263 /* Optionally enable RAM banks that may be off by default at reset */
264 #if !defined(DONT_ENABLE_DISABLED_RAMBANKS)
265     SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL0_SRAM_CTRL1_MASK | SYSCON_AHBCLKCTRL0_SRAM_CTRL2_MASK
266                           | SYSCON_AHBCLKCTRL0_SRAM_CTRL3_MASK | SYSCON_AHBCLKCTRL0_SRAM_CTRL4_MASK;
267 #endif
268   SystemInitHook();
269 }
270 
271 /* ----------------------------------------------------------------------------
272    -- SystemCoreClockUpdate()
273    ---------------------------------------------------------------------------- */
274 
SystemCoreClockUpdate(void)275 void SystemCoreClockUpdate (void) {
276     uint32_t clkRate = 0;
277     uint32_t prediv, postdiv;
278     uint64_t workRate;
279     uint64_t workRate1;
280 
281     switch (SYSCON->MAINCLKSELB & SYSCON_MAINCLKSELB_SEL_MASK)
282     {
283         case 0x00: /* MAINCLKSELA clock (main_clk_a)*/
284             switch (SYSCON->MAINCLKSELA & SYSCON_MAINCLKSELA_SEL_MASK)
285             {
286                 case 0x00: /* FRO 12 MHz (fro_12m) */
287                     clkRate = GetFro12MFreq();
288                     break;
289                 case 0x01: /* CLKIN (clk_in) */
290                     clkRate = GetExtClkFreq();
291                     break;
292                 case 0x02: /* Fro 1MHz (fro_1m) */
293                     clkRate = GetFro1MFreq();
294                     break;
295                 default: /* = 0x03 = FRO 96 MHz (fro_hf) */
296                     clkRate = GetFroHfFreq();
297                     break;
298             }
299             break;
300         case 0x01: /* PLL0 clock (pll0_clk)*/
301             switch (SYSCON->PLL0CLKSEL & SYSCON_PLL0CLKSEL_SEL_MASK)
302             {
303                 case 0x00: /* FRO 12 MHz (fro_12m) */
304                     clkRate = GetFro12MFreq();
305                     break;
306                 case 0x01: /* CLKIN (clk_in) */
307                     clkRate = GetExtClkFreq();
308                     break;
309                 case 0x02: /* Fro 1MHz (fro_1m) */
310                     clkRate = GetFro1MFreq();
311                     break;
312                 case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
313                     clkRate = GetOsc32KFreq();
314                     break;
315                 default:
316                     clkRate = 0UL;
317                     break;
318             }
319             if (((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_BYPASSPLL_MASK) == 0UL) && ((SYSCON->PLL0CTRL & SYSCON_PLL0CTRL_CLKEN_MASK) != 0UL) && ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_MASK) == 0UL) && ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL0_SSCG_MASK) == 0UL))
320             {
321                 prediv = findPll0PreDiv();
322                 postdiv = findPll0PostDiv();
323                 /* Adjust input clock */
324                 clkRate = clkRate / prediv;
325                 /* MDEC used for rate */
326                 workRate = (uint64_t)clkRate * (uint64_t)findPll0MMult();
327                 clkRate = (uint32_t)(workRate / ((uint64_t)postdiv));
328             }
329             break;
330         case 0x02: /* PLL1 clock (pll1_clk)*/
331             switch (SYSCON->PLL1CLKSEL & SYSCON_PLL1CLKSEL_SEL_MASK)
332             {
333                 case 0x00: /* FRO 12 MHz (fro_12m) */
334                     clkRate = GetFro12MFreq();
335                     break;
336                 case 0x01: /* CLKIN (clk_in) */
337                     clkRate = GetExtClkFreq();
338                     break;
339                 case 0x02: /* Fro 1MHz (fro_1m) */
340                     clkRate = GetFro1MFreq();
341                     break;
342                 case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
343                     clkRate = GetOsc32KFreq();
344                     break;
345                 default:
346                     clkRate = 0UL;
347                     break;
348             }
349             if (((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_BYPASSPLL_MASK) == 0UL) && ((SYSCON->PLL1CTRL & SYSCON_PLL1CTRL_CLKEN_MASK) != 0UL) && ((PMC->PDRUNCFG0 & PMC_PDRUNCFG0_PDEN_PLL1_MASK) == 0UL))
350             {
351                 /* PLL is not in bypass mode, get pre-divider, post-divider, and M divider */
352                 prediv = findPll1PreDiv();
353                 postdiv = findPll1PostDiv();
354                 /* Adjust input clock */
355                 clkRate = clkRate / prediv;
356 
357                 /* MDEC used for rate */
358                 workRate1 = (uint64_t)clkRate * (uint64_t)findPll1MMult();
359                 clkRate = (uint32_t)(workRate1 / ((uint64_t)postdiv));
360             }
361             break;
362         case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
363             clkRate = GetOsc32KFreq();
364             break;
365         default:
366             clkRate = 0UL;
367             break;
368     }
369     SystemCoreClock = clkRate / ((SYSCON->AHBCLKDIV & 0xFFUL) + 1UL);
370 }
371 
372 /* ----------------------------------------------------------------------------
373    -- SystemInitHook()
374    ---------------------------------------------------------------------------- */
375 
SystemInitHook(void)376 __attribute__ ((weak)) void SystemInitHook (void) {
377   /* Void implementation of the weak function. */
378 }
379