1 /*********************************************************************************************************************
2  * @file     system_XMC4500.c
3  * @brief    CMSIS Cortex-M4 Device Peripheral Access Layer Header File for the Infineon XMC4500 Device Series
4  * @version  V3.1.5
5  * @date     26. Sep 2017
6  *
7  * @cond
8  *********************************************************************************************************************
9  * Copyright (c) 2014-2018, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
13  * following conditions are met:
14  *
15  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16  * disclaimer.
17  *
18  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided with the distribution.
20  *
21  * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22  * products derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33  * Infineon Technologies AG dave@infineon.com).
34  *********************************************************************************************************************
35  *
36  ********************** Version History ***************************************
37  * V3.1.0, Dec 2014, Added options to configure clock settings
38  * V3.1.1, 01. Jun 2016, Fix masking of OSCHPCTRL value
39  * V3.1.2, 09. Feb 2017, Fix activation of USBPLL when SDMMC clock is enabled
40  * V3.1.3, 19. Jun 2017, Rely on cmsis_compiler.h instead of defining __WEAK
41  *                       Added support for ARM Compiler 6 (armclang)
42  * V3.1.4, 26. Sep 2017, Disable FPU if FPU_USED is zero
43  *                       Fixed include files
44  * V3.1.5, 29. Oct 2018, Fix variable location of SystemCoreClock and g_chipid for ARMCC compiler
45  ******************************************************************************
46  * @endcond
47  */
48 
49 /*******************************************************************************
50  * HEADER FILES
51  *******************************************************************************/
52 #include <string.h>
53 
54 #include <XMC4500.h>
55 #include "system_XMC4500.h"
56 
57 /*******************************************************************************
58  * MACROS
59  *******************************************************************************/
60 #define CHIPID_LOC ((uint8_t *)0x20000000UL)
61 
62 #define PMU_FLASH_WS          (0x3U)
63 
64 #define FPLL_FREQUENCY        (120000000U)
65 #define FOSCREF               (2500000U)
66 #define DELAY_CNT_50US_50MHZ  (2500UL)
67 #define DELAY_CNT_150US_50MHZ (7500UL)
68 #define DELAY_CNT_50US_60MHZ  (3000UL)
69 #define DELAY_CNT_50US_90MHZ  (4500UL)
70 #define DELAY_CNT_50US_120MHZ (6000UL)
71 
72 #define SCU_PLL_PLLSTAT_OSC_USABLE  (SCU_PLL_PLLSTAT_PLLHV_Msk | \
73                                      SCU_PLL_PLLSTAT_PLLLV_Msk | \
74                                      SCU_PLL_PLLSTAT_PLLSP_Msk)
75 
76 /*
77 //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
78 */
79 
80 /*
81 // <h> Clock configuration
82 */
83 
84 /*
85 //    <o> External crystal frequency [Hz]
86 //       <8000000=> 8MHz
87 //       <12000000=> 12MHz
88 //       <16000000=> 16MHz
89 //    <i> Defines external crystal frequency
90 //    <i> Default: 8MHz
91 */
92 #define OSCHP_FREQUENCY (12000000U)
93 
94 #if OSCHP_FREQUENCY == 8000000U
95 #define USB_PDIV (1U)
96 #define USB_NDIV (95U)
97 #define USB_DIV (3U)
98 
99 #elif OSCHP_FREQUENCY == 12000000U
100 #define USB_PDIV (1U)
101 #define USB_NDIV (63U)
102 #define USB_DIV (3U)
103 
104 #elif OSCHP_FREQUENCY == 16000000U
105 #define USB_PDIV (1U)
106 #define USB_NDIV (47U)
107 #define USB_DIV (3U)
108 
109 #else
110 #error "External crystal frequency not supported"
111 
112 #endif
113 
114 /*
115 //    <o> System clock (fSYS) source selection
116 //       <0=> Backup clock (24MHz)
117 //       <1=> Maximum clock frequency using PLL (120MHz)
118 //    <i> Default: Maximum clock frequency using PLL (120MHz)
119 */
120 #define SYS_CLOCK_SRC 1
121 #define SYS_CLOCK_SRC_OFI 0
122 #define SYS_CLOCK_SRC_PLL 1
123 
124 /*
125 //    <o> Backup clock calibration mode
126 //       <0=> Factory calibration
127 //       <1=> Automatic calibration
128 //    <i> Default: Automatic calibration
129 */
130 #define FOFI_CALIBRATION_MODE 1
131 #define FOFI_CALIBRATION_MODE_FACTORY 0
132 #define FOFI_CALIBRATION_MODE_AUTOMATIC 1
133 
134 /*
135 //    <o> Standby clock (fSTDBY) source selection
136 //       <0=> Internal slow oscillator (32768Hz)
137 //       <1=> External crystal (32768Hz)
138 //    <i> Default: Internal slow oscillator (32768Hz)
139 */
140 #define STDBY_CLOCK_SRC 0
141 #define STDBY_CLOCK_SRC_OSI 0
142 #define STDBY_CLOCK_SRC_OSCULP 1
143 
144 /*
145 //    <o> PLL clock source selection
146 //       <0=> External crystal
147 //       <1=> External direct input
148 //       <2=> Internal fast oscillator
149 //    <i> Default: External crystal
150 */
151 #define PLL_CLOCK_SRC 0
152 #define PLL_CLOCK_SRC_EXT_XTAL 0
153 #define PLL_CLOCK_SRC_EXT_DIRECT 1
154 #define PLL_CLOCK_SRC_OFI 2
155 
156 #if PLL_CLOCK_SRC == PLL_CLOCK_SRC_EXT_XTAL
157 #if OSCHP_FREQUENCY == 8000000U
158 #define PLL_PDIV (1U)
159 #define PLL_NDIV (89U)
160 #define PLL_K2DIV (2U)
161 
162 #elif OSCHP_FREQUENCY == 12000000U
163 #define PLL_PDIV (1U)
164 #define PLL_NDIV (79U)
165 #define PLL_K2DIV (3U)
166 
167 #elif OSCHP_FREQUENCY == 16000000U
168 #define PLL_PDIV (1U)
169 #define PLL_NDIV (59U)
170 #define PLL_K2DIV (3U)
171 
172 #else
173 #error "External crystal frequency not supported"
174 
175 #endif
176 
177 #define VCO ((OSCHP_FREQUENCY / (PLL_PDIV + 1UL)) * (PLL_NDIV + 1UL))
178 
179 #else /* PLL_CLOCK_SRC == PLL_CLOCK_SRC_EXT_XTAL */
180 
181 #define PLL_PDIV (1U)
182 #define PLL_NDIV (39U)
183 #define PLL_K2DIV (3U)
184 
185 #define VCO ((OFI_FREQUENCY / (PLL_PDIV + 1UL)) * (PLL_NDIV + 1UL))
186 
187 #endif /* PLL_CLOCK_SRC == PLL_CLOCK_SRC_OFI */
188 
189 #define PLL_K2DIV_0 ((VCO / OFI_FREQUENCY) - 1UL)
190 #define PLL_K2DIV_1 ((VCO / 60000000U) - 1UL)
191 #define PLL_K2DIV_2 ((VCO / 90000000U) - 1UL)
192 
193 #define SCU_CLK_CLKCLR_ENABLE_USBCLK SCU_CLK_CLKCLR_USBCDI_Msk
194 #define SCU_CLK_CLKCLR_ENABLE_MMCCLK SCU_CLK_CLKCLR_MMCCDI_Msk
195 #define SCU_CLK_CLKCLR_ENABLE_ETHCLK SCU_CLK_CLKCLR_ETH0CDI_Msk
196 #define SCU_CLK_CLKCLR_ENABLE_EBUCLK SCU_CLK_CLKCLR_EBUCDI_Msk
197 #define SCU_CLK_CLKCLR_ENABLE_CCUCLK SCU_CLK_CLKCLR_CCUCDI_Msk
198 #define SCU_CLK_CLKCLR_ENABLE_WDTCLK SCU_CLK_CLKCLR_WDTCDI_Msk
199 
200 #define SCU_CLK_USBCLKCR_USBSEL_USBPLL (0U << SCU_CLK_USBCLKCR_USBSEL_Pos)
201 #define SCU_CLK_USBCLKCR_USBSEL_PLL    (1U << SCU_CLK_USBCLKCR_USBSEL_Pos)
202 
203 #define SCU_CLK_WDTCLKCR_WDTSEL_OFI      (0U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
204 #define SCU_CLK_WDTCLKCR_WDTSEL_STANDBY  (1U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
205 #define SCU_CLK_WDTCLKCR_WDTSEL_PLL      (2U << SCU_CLK_WDTCLKCR_WDTSEL_Pos)
206 
207 #define SCU_CLK_EXTCLKCR_ECKSEL_SYS      (0U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
208 #define SCU_CLK_EXTCLKCR_ECKSEL_USBPLL   (2U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
209 #define SCU_CLK_EXTCLKCR_ECKSEL_PLL      (3U << SCU_CLK_EXTCLKCR_ECKSEL_Pos)
210 
211 #define EXTCLK_PIN_P0_8  (0)
212 #define EXTCLK_PIN_P1_15 (1)
213 
214 /*
215 //    <h> Clock tree
216 //        <o1.0> CPU clock divider
217 //                   <0=> fCPU = fSYS
218 //                   <1=> fCPU = fSYS / 2
219 //        <o2.0>  Peripheral clock divider
220 //                     <0=> fPB	= fCPU
221 //                     <1=> fPB	= fCPU / 2
222 //        <e.4> Enable CCU clock
223 //             <o3.0>  CCU clock divider
224 //                     <0=> fCCU = fCPU
225 //                     <1=> fCCU = fCPU / 2
226 //        </e>
227 //        <e.5> Enable WDT clock
228 //             <o4.0..7>  WDT clock divider <1-256><#-1>
229 //             <o4.16..17> WDT clock source <0=> fOFI
230 //                                          <1=> fSTDBY
231 //                                          <2=> fPLL
232 //        </e>
233 //        <e.3> Enable EBU clock
234 //             <o5.0..5>  EBU clock divider  <1-64><#-1>
235 //        </e>
236 //        <e.2> Enable ETH clock
237 //        </e>
238 //        <e.1> Enable MMC clock
239 //        </e>
240 //        <e.0> Enable USB clock
241 //             <o6.16> USB clock source <0=> USBPLL
242 //                                      <1=> PLL
243 //        </e>
244 //        <e7> External Clock configuration
245 //            <o8.0..1> External Clock Source Selection
246 //                  <0=> System clock
247 //                  <2=> USB PLL clock
248 //                  <3=> PLL clock
249 //            <o8.16..24> External Clock divider <1-512><#-1>
250 //            <i> Only valid for USB PLL and PLL clocks
251 //            <o9.0> External Clock Pin Selection
252 //                  <0=> P0.8
253 //                  <1=> P1.15
254 //        </e>
255 //    </h>
256 */
257 #define ENABLE_SCUCLK (0U)
258 #define CPUCLKDIV (0U)
259 #define PBCLKDIV (0U)
260 #define CCUCLKDIV (0U)
261 #define WDTCLKDIV (0U | SCU_CLK_WDTCLKCR_WDTSEL_OFI)
262 #define EBUCLKDIV (0U)
263 #define USBCLKDIV (0U | SCU_CLK_USBCLKCR_USBSEL_USBPLL | USB_DIV)
264 
265 #define ENABLE_EXTCLK (0U)
266 #define EXTCLKDIV (0U | SCU_CLK_EXTCLKCR_ECKSEL_SYS)
267 #define EXTCLK_PIN (0U)
268 
269 #define ENABLE_PLL \
270     (SYS_CLOCK_SRC == SYS_CLOCK_SRC_PLL) || \
271     ((ENABLE_SCUCLK & SCU_CLK_CLKSET_EBUCEN_Msk) != 0) || \
272     (((ENABLE_SCUCLK & SCU_CLK_CLKSET_USBCEN_Msk) != 0) && ((USBCLKDIV & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_PLL)) || \
273     (((ENABLE_SCUCLK & SCU_CLK_CLKSET_WDTCEN_Msk) != 0) && ((WDTCLKDIV & SCU_CLK_WDTCLKCR_WDTSEL_Msk) == SCU_CLK_WDTCLKCR_WDTSEL_PLL))
274 
275 #define ENABLE_USBPLL \
276     ((((ENABLE_SCUCLK & SCU_CLK_CLKSET_USBCEN_Msk) != 0) && ((USBCLKDIV & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_USBPLL)) ||\
277      (((ENABLE_SCUCLK & SCU_CLK_CLKCLR_ENABLE_MMCCLK) != 0) && ((USBCLKDIV & SCU_CLK_USBCLKCR_USBSEL_Msk) == SCU_CLK_USBCLKCR_USBSEL_USBPLL)))
278 /*
279 // </h>
280 */
281 
282 /*
283 //-------- <<< end of configuration section >>> ------------------
284 */
285 
286 /*******************************************************************************
287  * GLOBAL VARIABLES
288  *******************************************************************************/
289 #if defined ( __CC_ARM )
290 uint32_t SystemCoreClock __attribute__((at(0x2000FFC0)));
291 uint8_t g_chipid[16] __attribute__((at(0x2000FFC4)));
292 #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
293 uint32_t SystemCoreClock __attribute__((section(".bss.ARM.__at_0x2000FFC0")));
294 uint8_t g_chipid[16] __attribute__((section(".bss.ARM.__at_0x2000FFC4")));
295 #elif defined ( __ICCARM__ )
296 __no_init uint32_t SystemCoreClock;
297 __no_init uint8_t g_chipid[16];
298 #elif defined ( __GNUC__ )
299 uint32_t SystemCoreClock __attribute__((section(".no_init")));
300 uint8_t g_chipid[16] __attribute__((section(".no_init")));
301 #elif defined ( __TASKING__ )
302 uint32_t SystemCoreClock __at( 0x2000FFC0 );
303 uint8_t g_chipid[16] __at( 0x2000FFC4 );
304 #endif
305 
306 extern uint32_t __Vectors;
307 
308 /*******************************************************************************
309  * LOCAL FUNCTIONS
310  *******************************************************************************/
delay(uint32_t cycles)311 static void delay(uint32_t cycles)
312 {
313   volatile uint32_t i;
314 
315   for(i = 0UL; i < cycles ;++i)
316   {
317     __NOP();
318   }
319 }
320 
321 /*******************************************************************************
322  * API IMPLEMENTATION
323  *******************************************************************************/
324 
SystemInit(void)325 __WEAK void SystemInit(void)
326 {
327   memcpy(g_chipid, CHIPID_LOC, 16);
328 
329   SystemCoreSetup();
330   SystemCoreClockSetup();
331 }
332 
SystemCoreSetup(void)333 __WEAK void SystemCoreSetup(void)
334 {
335   uint32_t temp;
336 
337   /* relocate vector table */
338   __disable_irq();
339   SCB->VTOR = (uint32_t)(&__Vectors);
340   __DSB();
341   __enable_irq();
342 
343   /* __FPU_PRESENT = 1 defined in device header file */
344   /* __FPU_USED value depends on compiler/linker options. */
345   /* __FPU_USED = 0 if -mfloat-abi=soft is selected */
346   /* __FPU_USED = 1 if -mfloat-abi=softfp or –mfloat-abi=hard */
347 
348 #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
349   SCB->CPACR |= ((3UL << 10*2) |                 /* set CP10 Full Access */
350                  (3UL << 11*2)  );               /* set CP11 Full Access */
351 #else
352   SCB->CPACR = 0;
353 #endif
354 
355   /* Enable unaligned memory access - SCB_CCR.UNALIGN_TRP = 0 */
356   SCB->CCR &= ~(SCB_CCR_UNALIGN_TRP_Msk);
357 
358   temp = FLASH0->FCON;
359   temp &= ~FLASH_FCON_WSPFLASH_Msk;
360   temp |= PMU_FLASH_WS;
361   FLASH0->FCON = temp;
362 }
363 
SystemCoreClockSetup(void)364 __WEAK void SystemCoreClockSetup(void)
365 {
366 #if FOFI_CALIBRATION_MODE == FOFI_CALIBRATION_MODE_FACTORY
367   /* Enable factory calibration */
368   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FOTR_Msk;
369 #else
370   /* Automatic calibration uses the fSTDBY */
371 
372   /* Enable HIB domain */
373   /* Power up HIB domain if and only if it is currently powered down */
374   if((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0)
375   {
376     SCU_POWER->PWRSET |= SCU_POWER_PWRSET_HIB_Msk;
377 
378     while((SCU_POWER->PWRSTAT & SCU_POWER_PWRSTAT_HIBEN_Msk) == 0)
379     {
380       /* wait until HIB domain is enabled */
381     }
382   }
383 
384   /* Remove the reset only if HIB domain were in a state of reset */
385   if((SCU_RESET->RSTSTAT) & SCU_RESET_RSTSTAT_HIBRS_Msk)
386   {
387     SCU_RESET->RSTCLR |= SCU_RESET_RSTCLR_HIBRS_Msk;
388     delay(DELAY_CNT_150US_50MHZ);
389   }
390 
391 #if STDBY_CLOCK_SRC == STDBY_CLOCK_SRC_OSCULP
392   /* Enable OSC_ULP */
393   if ((SCU_HIBERNATE->OSCULCTRL & SCU_HIBERNATE_OSCULCTRL_MODE_Msk) != 0UL)
394   {
395     /*enable OSC_ULP*/
396     while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_OSCULCTRL_Msk)
397     {
398       /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
399     }
400     SCU_HIBERNATE->OSCULCTRL &= ~SCU_HIBERNATE_OSCULCTRL_MODE_Msk;
401 
402     /* Check if the clock is OK using OSCULP Oscillator Watchdog*/
403     while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCR_Msk)
404     {
405       /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
406     }
407     SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_ULPWDGEN_Msk;
408 
409     /* wait till clock is stable */
410     do
411     {
412       while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCLR_Msk)
413       {
414         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
415       }
416       SCU_HIBERNATE->HDCLR |= SCU_HIBERNATE_HDCLR_ULPWDG_Msk;
417 
418       delay(DELAY_CNT_50US_50MHZ);
419 
420     } while ((SCU_HIBERNATE->HDSTAT & SCU_HIBERNATE_HDSTAT_ULPWDG_Msk) != 0UL);
421 
422   }
423 
424   /* now OSC_ULP is running and can be used*/
425   /* Select OSC_ULP as the clock source for RTC and STDBY*/
426   while (SCU_GENERAL->MIRRSTS & SCU_GENERAL_MIRRSTS_HDCR_Msk)
427   {
428     /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
429   }
430   SCU_HIBERNATE->HDCR |= SCU_HIBERNATE_HDCR_RCS_Msk | SCU_HIBERNATE_HDCR_STDBYSEL_Msk;
431 
432 #endif /* STDBY_CLOCK_SRC == STDBY_CLOCK_SRC_OSCULP */
433 
434   /* Enable automatic calibration of internal fast oscillator */
435   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_AOTREN_Msk;
436 #endif /* FOFI_CALIBRATION_MODE == FOFI_CALIBRATION_MODE_AUTOMATIC */
437 
438   delay(DELAY_CNT_50US_50MHZ);
439 
440 #if ENABLE_PLL
441 
442   /* enable PLL */
443   SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
444 
445 #if PLL_CLOCK_SRC != PLL_CLOCK_SRC_OFI
446   /* enable OSC_HP */
447   if ((SCU_OSC->OSCHPCTRL & SCU_OSC_OSCHPCTRL_MODE_Msk) != 0U)
448   {
449     SCU_OSC->OSCHPCTRL &= ~(SCU_OSC_OSCHPCTRL_MODE_Msk | SCU_OSC_OSCHPCTRL_OSCVAL_Msk);
450     SCU_OSC->OSCHPCTRL |= ((OSCHP_GetFrequency() / FOSCREF) - 1UL) << SCU_OSC_OSCHPCTRL_OSCVAL_Pos;
451 
452     /* select OSC_HP clock as PLL input */
453     SCU_PLL->PLLCON2 &= ~SCU_PLL_PLLCON2_PINSEL_Msk;
454 
455     /* restart OSC Watchdog */
456     SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;
457 
458     while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_OSC_USABLE) != SCU_PLL_PLLSTAT_OSC_USABLE)
459     {
460       /* wait till OSC_HP output frequency is usable */
461     }
462   }
463 #else /* PLL_CLOCK_SRC != PLL_CLOCK_SRC_OFI */
464 
465   /* select backup clock as PLL input */
466   SCU_PLL->PLLCON2 |= SCU_PLL_PLLCON2_PINSEL_Msk;
467 #endif
468 
469   /* Go to bypass the Main PLL */
470   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_VCOBYP_Msk;
471 
472   /* disconnect Oscillator from PLL */
473   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_FINDIS_Msk;
474 
475   /* Setup divider settings for main PLL */
476   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
477                       (PLL_K2DIV_0 << SCU_PLL_PLLCON1_K2DIV_Pos) |
478                       (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
479 
480   /* Set OSCDISCDIS */
481   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
482 
483   /* connect Oscillator to PLL */
484   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_FINDIS_Msk;
485 
486   /* restart PLL Lock detection */
487   SCU_PLL->PLLCON0 |= SCU_PLL_PLLCON0_RESLD_Msk;
488 
489   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) == 0U)
490   {
491     /* wait for PLL Lock */
492   }
493 
494   /* Disable bypass- put PLL clock back */
495   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_VCOBYP_Msk;
496   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOBYST_Msk) != 0U)
497   {
498     /* wait for normal mode */
499   }
500 #endif /* ENABLE_PLL */
501 
502 #if (SYS_CLOCK_SRC == SYS_CLOCK_SRC_PLL)
503   /* Switch system clock to PLL */
504   SCU_CLK->SYSCLKCR |= SCU_CLK_SYSCLKCR_SYSSEL_Msk;
505 #else
506   /* Switch system clock to backup clock */
507   SCU_CLK->SYSCLKCR &= ~SCU_CLK_SYSCLKCR_SYSSEL_Msk;
508 #endif
509 
510   /* Before scaling to final frequency we need to setup the clock dividers */
511   SCU_CLK->PBCLKCR = PBCLKDIV;
512   SCU_CLK->CPUCLKCR = CPUCLKDIV;
513   SCU_CLK->CCUCLKCR = CCUCLKDIV;
514   SCU_CLK->WDTCLKCR = WDTCLKDIV;
515   SCU_CLK->EBUCLKCR = EBUCLKDIV;
516   SCU_CLK->USBCLKCR = USBCLKDIV;
517 
518 #if ENABLE_PLL
519   /* PLL frequency stepping...*/
520   /* Reset OSCDISCDIS */
521   SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCDISCDIS_Msk;
522 
523   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
524 	                    (PLL_K2DIV_1 << SCU_PLL_PLLCON1_K2DIV_Pos) |
525 	                    (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
526 
527 
528   delay(DELAY_CNT_50US_60MHZ);
529   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) == 0U)
530   {
531     /* wait for PLL Lock */
532   }
533 
534   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
535 	                    (PLL_K2DIV_2 << SCU_PLL_PLLCON1_K2DIV_Pos) |
536 	                    (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
537 
538 
539   delay(DELAY_CNT_50US_90MHZ);
540   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) == 0U)
541   {
542     /* wait for PLL Lock */
543   }
544 
545   SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
546 	                    (PLL_K2DIV << SCU_PLL_PLLCON1_K2DIV_Pos) |
547 	                    (PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));
548 
549 
550   delay(DELAY_CNT_50US_120MHZ);
551   while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk) == 0U)
552   {
553     /* wait for PLL Lock */
554   }
555 
556   SCU_TRAP->TRAPCLR = SCU_TRAP_TRAPCLR_SOSCWDGT_Msk | SCU_TRAP_TRAPCLR_SVCOLCKT_Msk;
557 #endif /* ENABLE_PLL */
558 
559 #if ENABLE_USBPLL
560   /* enable USB PLL first */
561   SCU_PLL->USBPLLCON &= ~(SCU_PLL_USBPLLCON_VCOPWD_Msk | SCU_PLL_USBPLLCON_PLLPWD_Msk);
562 
563   /* USB PLL uses as clock input the OSC_HP */
564   /* check and if not already running enable OSC_HP */
565   if ((SCU_OSC->OSCHPCTRL & SCU_OSC_OSCHPCTRL_MODE_Msk) != 0U)
566   {
567     /* check if Main PLL is switched on for OSC WDG*/
568     if ((SCU_PLL->PLLCON0 &(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk)) != 0UL)
569     {
570       /* enable PLL first */
571       SCU_PLL->PLLCON0 &= ~(SCU_PLL_PLLCON0_VCOPWD_Msk | SCU_PLL_PLLCON0_PLLPWD_Msk);
572     }
573 
574     SCU_OSC->OSCHPCTRL &= ~(SCU_OSC_OSCHPCTRL_MODE_Msk | SCU_OSC_OSCHPCTRL_OSCVAL_Msk);
575     SCU_OSC->OSCHPCTRL |= ((OSCHP_GetFrequency() / FOSCREF) - 1UL) << SCU_OSC_OSCHPCTRL_OSCVAL_Pos;
576 
577     /* restart OSC Watchdog */
578     SCU_PLL->PLLCON0 &= ~SCU_PLL_PLLCON0_OSCRES_Msk;
579 
580     while ((SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_OSC_USABLE) != SCU_PLL_PLLSTAT_OSC_USABLE)
581     {
582       /* wait till OSC_HP output frequency is usable */
583     }
584   }
585 
586   /* Setup USB PLL */
587   /* Go to bypass the USB PLL */
588   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_VCOBYP_Msk;
589 
590   /* disconnect Oscillator from USB PLL */
591   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_FINDIS_Msk;
592 
593   /* Setup Divider settings for USB PLL */
594   SCU_PLL->USBPLLCON = ((USB_NDIV << SCU_PLL_USBPLLCON_NDIV_Pos) |
595                         (USB_PDIV << SCU_PLL_USBPLLCON_PDIV_Pos));
596 
597   /* Set OSCDISCDIS */
598   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_OSCDISCDIS_Msk;
599 
600   /* connect Oscillator to USB PLL */
601   SCU_PLL->USBPLLCON &= ~SCU_PLL_USBPLLCON_FINDIS_Msk;
602 
603   /* restart PLL Lock detection */
604   SCU_PLL->USBPLLCON |= SCU_PLL_USBPLLCON_RESLD_Msk;
605 
606   while ((SCU_PLL->USBPLLSTAT & SCU_PLL_USBPLLSTAT_VCOLOCK_Msk) == 0U)
607   {
608     /* wait for PLL Lock */
609   }
610 #endif /* (USBCLKDIV & SCU_CLK_USBCLKCR_USBSEL_Msk) */
611 
612   /* Enable selected clocks */
613   SCU_CLK->CLKSET = ENABLE_SCUCLK;
614 
615 #if ENABLE_EXTCLK == 1
616   /* Configure external clock */
617   SCU_CLK->EXTCLKCR = EXTCLKDIV;
618 
619 #if EXTCLK_PIN == EXTCLK_PIN_P1_15
620   /* P1.15 */
621   PORT1->PDR1 &= ~PORT1_PDR1_PD15_Msk;
622   PORT1->IOCR12 = (PORT1->IOCR12 & ~PORT0_IOCR12_PC15_Msk) | (0x11U << PORT0_IOCR12_PC15_Pos);
623 #else
624   /* P0.8 */
625   PORT0->HWSEL &= ~PORT0_HWSEL_HW8_Msk;
626   PORT0->PDR1 &= ~PORT0_PDR1_PD8_Msk;
627   PORT0->IOCR8 = (PORT0->IOCR8 & ~PORT0_IOCR8_PC8_Msk) | (0x11U << PORT0_IOCR8_PC8_Pos);
628 #endif
629 
630 #endif  /* ENABLE_EXTCLK == 1  */
631 
632   SystemCoreClockUpdate();
633 }
634 
SystemCoreClockUpdate(void)635 __WEAK void SystemCoreClockUpdate(void)
636 {
637   uint32_t pdiv;
638   uint32_t ndiv;
639   uint32_t kdiv;
640   uint32_t temp;
641 
642   if (SCU_CLK->SYSCLKCR & SCU_CLK_SYSCLKCR_SYSSEL_Msk)
643   {
644     /* fPLL is clock source for fSYS */
645     if(SCU_PLL->PLLCON2 & SCU_PLL_PLLCON2_PINSEL_Msk)
646     {
647       /* PLL input clock is the backup clock (fOFI) */
648       temp = OFI_FREQUENCY;
649     }
650     else
651     {
652       /* PLL input clock is the high performance osicllator (fOSCHP) */
653       temp = OSCHP_GetFrequency();
654     }
655 
656     /* check if PLL is locked */
657     if (SCU_PLL->PLLSTAT & SCU_PLL_PLLSTAT_VCOLOCK_Msk)
658     {
659       /* PLL normal mode */
660       /* read back divider settings */
661       pdiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_PDIV_Msk) >> SCU_PLL_PLLCON1_PDIV_Pos) + 1;
662       ndiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_NDIV_Msk) >> SCU_PLL_PLLCON1_NDIV_Pos) + 1;
663       kdiv = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_K2DIV_Msk) >> SCU_PLL_PLLCON1_K2DIV_Pos) + 1;
664 
665       temp = (temp / (pdiv * kdiv)) * ndiv;
666     }
667     else
668     {
669       /* PLL prescalar mode */
670       /* read back divider settings */
671       kdiv  = ((SCU_PLL->PLLCON1 & SCU_PLL_PLLCON1_K1DIV_Msk) >> SCU_PLL_PLLCON1_K1DIV_Pos) + 1;
672 
673       temp = (temp / kdiv);
674     }
675   }
676   else
677   {
678     /* fOFI is clock source for fSYS */
679     temp = OFI_FREQUENCY;
680   }
681 
682   temp = temp / ((SCU_CLK->SYSCLKCR & SCU_CLK_SYSCLKCR_SYSDIV_Msk) + 1);
683   temp = temp / ((SCU_CLK->CPUCLKCR & SCU_CLK_CPUCLKCR_CPUDIV_Msk) + 1);
684 
685   SystemCoreClock = temp;
686 }
687 
OSCHP_GetFrequency(void)688 __WEAK uint32_t OSCHP_GetFrequency(void)
689 {
690   return OSCHP_FREQUENCY;
691 }
692