1 /*
2 ** ###################################################################
3 **     Processor:           MKW24D512VHA5
4 **     Compilers:           Keil ARM C/C++ Compiler
5 **                          Freescale C/C++ for Embedded ARM
6 **                          GNU C Compiler
7 **                          IAR ANSI C/C++ Compiler for ARM
8 **                          MCUXpresso Compiler
9 **
10 **     Reference manual:    MKW2xDRM Rev.2  July 2014
11 **     Version:             rev. 2.0, 2014-11-26
12 **     Build:               b170112
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 (c) 2016 Freescale Semiconductor, Inc.
20 **     Copyright 2016 - 2017 NXP
21 **     Redistribution and use in source and binary forms, with or without modification,
22 **     are permitted provided that the following conditions are met:
23 **
24 **     o Redistributions of source code must retain the above copyright notice, this list
25 **       of conditions and the following disclaimer.
26 **
27 **     o Redistributions in binary form must reproduce the above copyright notice, this
28 **       list of conditions and the following disclaimer in the documentation and/or
29 **       other materials provided with the distribution.
30 **
31 **     o Neither the name of the copyright holder nor the names of its
32 **       contributors may be used to endorse or promote products derived from this
33 **       software without specific prior written permission.
34 **
35 **     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
36 **     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
37 **     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 **     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
39 **     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 **     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
41 **     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
42 **     ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43 **     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44 **     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 **
46 **     http:                 www.nxp.com
47 **     mail:                 support@nxp.com
48 **
49 **     Revisions:
50 **     - rev. 1.0 (2013-11-22)
51 **         Initial version.
52 **     - rev. 2.0 (2014-11-26)
53 **         update of SystemInit() imlementation
54 **         Module access macro module_BASES replaced by module_BASE_PTRS.
55 **         Register accessor macros added to the memory map.
56 **         MCG - bit LOLS in MCG_S register renamed to LOLS0.
57 **         DAC0 registers removed.
58 **
59 ** ###################################################################
60 */
61 
62 /*!
63  * @file MKW24D5
64  * @version 2.0
65  * @date 2014-11-26
66  * @brief Device specific configuration file for MKW24D5 (implementation file)
67  *
68  * Provides a system configuration function and a global variable that contains
69  * the system frequency. It configures the device and initializes the oscillator
70  * (PLL) that is part of the microcontroller device.
71  */
72 
73 #include <stdint.h>
74 #include "fsl_device_registers.h"
75 
76 
77 /* ----------------------------------------------------------------------------
78    -- ExtClk_Setup_HookUp()
79    ---------------------------------------------------------------------------- */
80 
81 #pragma weak ExtClk_Setup_HookUp
ExtClk_Setup_HookUp(uint32_t clk_out_value)82 uint8_t ExtClk_Setup_HookUp(uint32_t clk_out_value) {
83   uint8_t result = 0;
84   switch (clk_out_value) {
85   case 4000000U:
86     /* Start XCVR clock in order to derive MCGOUTCLK */
87     SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK; /* Ungate PORTB and PORTC clock*/
88     GPIOB->PDDR |= 0x00080000u; /* Set PORTB.19 as output - XCVR RESET pin */
89     GPIOC->PDDR |= 0x00000001u; /* Set PORTC.0 as output - XCVR GPIO5 pin */
90     PORTB->PCR[19] = (PORTB->PCR[19] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(0x01u); /* PORTB.19 as GPIO */
91     PORTC->PCR[0]  = (PORTC->PCR[0] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(0x01u); /* PORTC.0 as GPIO*/
92     GPIOC->PCOR = 0x00000001u; /* Clear XCVR GPIO5 pin*/
93     GPIOB->PCOR = 0x00080000u; /* Clear XCVR RESET pin*/
94     GPIOB->PSOR = 0x00080000u; /* Set XCVR RESET pin*/
95     result =  1U;  /*  The output was set successfully */
96     break;
97   case 0U:
98     /* No initialization, modem remains in the reset state */
99     result =  1U;  /*  The output was set successfully */
100     break;
101   default:
102     result = 0U; /* Requested value cannot be set */
103     break;
104   }
105   return result;
106 }
107 
108 
109 /* ----------------------------------------------------------------------------
110    -- Core clock
111    ---------------------------------------------------------------------------- */
112 
113 uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
114 
115 /* ----------------------------------------------------------------------------
116    -- SystemInit()
117    ---------------------------------------------------------------------------- */
118 
SystemInit(void)119 void SystemInit (void) {
120   /* Watchdog disable */
121 #if (DISABLE_WDOG)
122   /* WDOG->UNLOCK: WDOGUNLOCK=0xC520 */
123   WDOG->UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xC520); /* Key 1 */
124   /* WDOG->UNLOCK: WDOGUNLOCK=0xD928 */
125   WDOG->UNLOCK = WDOG_UNLOCK_WDOGUNLOCK(0xD928); /* Key 2 */
126   /* WDOG->STCTRLH: ?=0,DISTESTWDOG=0,BYTESEL=0,TESTSEL=0,TESTWDOG=0,?=0,?=1,WAITEN=1,STOPEN=1,DBGEN=0,ALLOWUPDATE=1,WINEN=0,IRQRSTEN=0,CLKSRC=1,WDOGEN=0 */
127   WDOG->STCTRLH = WDOG_STCTRLH_BYTESEL(0x00) |
128                  WDOG_STCTRLH_WAITEN_MASK |
129                  WDOG_STCTRLH_STOPEN_MASK |
130                  WDOG_STCTRLH_ALLOWUPDATE_MASK |
131                  WDOG_STCTRLH_CLKSRC_MASK |
132                  0x0100U;
133 #endif /* (DISABLE_WDOG) */
134 
135 }
136 
137 /* ----------------------------------------------------------------------------
138    -- SystemCoreClockUpdate()
139    ---------------------------------------------------------------------------- */
140 
SystemCoreClockUpdate(void)141 void SystemCoreClockUpdate (void) {
142 
143   uint32_t MCGOUTClock;                /* Variable to store output clock frequency of the MCG module */
144   uint16_t Divider;
145 
146   if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x00U) {
147     /* Output of FLL or PLL is selected */
148     if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x00U) {
149       /* FLL is selected */
150       if ((MCG->C1 & MCG_C1_IREFS_MASK) == 0x00U) {
151         /* External reference clock is selected */
152         if((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x00U) {
153           MCGOUTClock = CPU_XTAL_CLK_HZ; /* System oscillator drives MCG clock */
154         } else {
155           MCGOUTClock = CPU_XTAL32k_CLK_HZ; /* RTC 32 kHz oscillator drives MCG clock */
156         }
157         if (((MCG->C2 & MCG_C2_RANGE0_MASK) != 0x00U) && ((MCG->C7 & MCG_C7_OSCSEL_MASK) != 0x01U)) {
158           switch (MCG->C1 & MCG_C1_FRDIV_MASK) {
159           case 0x38U:
160             Divider = 1536U;
161             break;
162           case 0x30U:
163             Divider = 1280U;
164             break;
165           default:
166             Divider = (uint16_t)(32LU << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT));
167             break;
168           }
169         } else {/* ((MCG->C2 & MCG_C2_RANGE_MASK) != 0x00U) */
170           Divider = (uint16_t)(1LU << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT));
171         }
172         MCGOUTClock = (MCGOUTClock / Divider); /* Calculate the divided FLL reference clock */
173       } else { /* (!((MCG->C1 & MCG_C1_IREFS_MASK) == 0x00U)) */
174         MCGOUTClock = CPU_INT_SLOW_CLK_HZ; /* The slow internal reference clock is selected */
175       } /* (!((MCG->C1 & MCG_C1_IREFS_MASK) == 0x00U)) */
176       /* Select correct multiplier to calculate the MCG output clock  */
177       switch (MCG->C4 & (MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) {
178         case 0x00U:
179           MCGOUTClock *= 640U;
180           break;
181         case 0x20U:
182           MCGOUTClock *= 1280U;
183           break;
184         case 0x40U:
185           MCGOUTClock *= 1920U;
186           break;
187         case 0x60U:
188           MCGOUTClock *= 2560U;
189           break;
190         case 0x80U:
191           MCGOUTClock *= 732U;
192           break;
193         case 0xA0U:
194           MCGOUTClock *= 1464U;
195           break;
196         case 0xC0U:
197           MCGOUTClock *= 2197U;
198           break;
199         case 0xE0U:
200           MCGOUTClock *= 2929U;
201           break;
202         default:
203           break;
204       }
205     } else { /* (!((MCG->C6 & MCG_C6_PLLS_MASK) == 0x00U)) */
206       /* PLL is selected */
207       Divider = (((uint16_t)MCG->C5 & MCG_C5_PRDIV0_MASK) + 0x01U);
208       MCGOUTClock = (uint32_t)(CPU_XTAL_CLK_HZ / Divider); /* Calculate the PLL reference clock */
209       Divider = (((uint16_t)MCG->C6 & MCG_C6_VDIV0_MASK) + 24U);
210       MCGOUTClock *= Divider;          /* Calculate the MCG output clock */
211     } /* (!((MCG->C6 & MCG_C6_PLLS_MASK) == 0x00U)) */
212   } else if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x40U) {
213     /* Internal reference clock is selected */
214     if ((MCG->C2 & MCG_C2_IRCS_MASK) == 0x00U) {
215       MCGOUTClock = CPU_INT_SLOW_CLK_HZ; /* Slow internal reference clock selected */
216     } else { /* (!((MCG->C2 & MCG_C2_IRCS_MASK) == 0x00U)) */
217       Divider = (uint16_t)(0x01LU << ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT));
218       MCGOUTClock = (uint32_t) (CPU_INT_FAST_CLK_HZ / Divider); /* Fast internal reference clock selected */
219     } /* (!((MCG->C2 & MCG_C2_IRCS_MASK) == 0x00U)) */
220   } else if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80U) {
221     /* External reference clock is selected */
222     if((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x00U) {
223       MCGOUTClock = CPU_XTAL_CLK_HZ;   /* System oscillator drives MCG clock */
224     } else {
225       MCGOUTClock = CPU_XTAL32k_CLK_HZ; /* RTC 32 kHz oscillator drives MCG clock */
226     }
227   } else { /* (!((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80U)) */
228     /* Reserved value */
229     return;
230   } /* (!((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80U)) */
231   SystemCoreClock = (MCGOUTClock / (0x01U + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT)));
232 }
233