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