1 /*
2  * Copyright (c) 2014-2015 Wind River Systems, Inc.
3  * Copyright (c) 2016, Freescale Semiconductor, Inc.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @file
10  * @brief System/hardware module for fsl_frdm_k64f platform
11  *
12  * This module provides routines to initialize and support board-level
13  * hardware for the fsl_frdm_k64f platform.
14  */
15 
16 #include <zephyr/kernel.h>
17 #include <zephyr/device.h>
18 #include <zephyr/init.h>
19 #include <soc.h>
20 #include <zephyr/drivers/uart.h>
21 #include <fsl_common.h>
22 #include <fsl_clock.h>
23 
24 #include <cmsis_core.h>
25 
26 #define LPUART0SRC_OSCERCLK     (1)
27 
28 #define TIMESRC_OSCERCLK        (2)
29 
30 #define RUNM_HSRUN              (3)
31 
32 #define CLOCK_NODEID(clk) \
33 	DT_CHILD(DT_INST(0, nxp_kinetis_sim), clk)
34 
35 #define CLOCK_DIVIDER(clk) \
36 	DT_PROP_OR(CLOCK_NODEID(clk), clock_div, 1) - 1
37 
38 static const osc_config_t oscConfig = {
39 	.freq = CONFIG_OSC_XTAL0_FREQ,
40 	.capLoad = 0,
41 
42 #if defined(CONFIG_OSC_EXTERNAL)
43 	.workMode = kOSC_ModeExt,
44 #elif defined(CONFIG_OSC_LOW_POWER)
45 	.workMode = kOSC_ModeOscLowPower,
46 #elif defined(CONFIG_OSC_HIGH_GAIN)
47 	.workMode = kOSC_ModeOscHighGain,
48 #else
49 #error "An oscillator mode must be defined"
50 #endif
51 
52 	.oscerConfig = {
53 		.enableMode = kOSC_ErClkEnable,
54 #if (defined(FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER) && \
55 	FSL_FEATURE_OSC_HAS_EXT_REF_CLOCK_DIVIDER)
56 		.erclkDiv = 0U,
57 #endif
58 	},
59 };
60 
61 static const mcg_pll_config_t pll0Config = {
62 	.enableMode = 0U,
63 	.prdiv = CONFIG_MCG_PRDIV0,
64 	.vdiv = CONFIG_MCG_VDIV0,
65 };
66 
67 static const sim_clock_config_t simConfig = {
68 	.pllFllSel = DT_PROP(DT_INST(0, nxp_kinetis_sim), pllfll_select),
69 	.er32kSrc = DT_PROP(DT_INST(0, nxp_kinetis_sim), er32k_select),
70 	.clkdiv1 = SIM_CLKDIV1_OUTDIV1(CLOCK_DIVIDER(core_clk)) |
71 		   SIM_CLKDIV1_OUTDIV2(CLOCK_DIVIDER(bus_clk)) |
72 		   SIM_CLKDIV1_OUTDIV3(CLOCK_DIVIDER(flexbus_clk)) |
73 		   SIM_CLKDIV1_OUTDIV4(CLOCK_DIVIDER(flash_clk)),
74 };
75 
76 /**
77  *
78  * @brief Initialize the system clock
79  *
80  * This routine will configure the multipurpose clock generator (MCG) to
81  * set up the system clock.
82  * The MCG has nine possible modes, including Stop mode.  This routine assumes
83  * that the current MCG mode is FLL Engaged Internal (FEI), as from reset.
84  * It transitions through the FLL Bypassed External (FBE) and
85  * PLL Bypassed External (PBE) modes to get to the desired
86  * PLL Engaged External (PEE) mode and generate the maximum 120 MHz system
87  * clock.
88  *
89  */
clock_init(void)90 static ALWAYS_INLINE void clock_init(void)
91 {
92 	CLOCK_SetSimSafeDivs();
93 
94 	CLOCK_InitOsc0(&oscConfig);
95 	CLOCK_SetXtal0Freq(CONFIG_OSC_XTAL0_FREQ);
96 
97 	CLOCK_BootToPeeMode(kMCG_OscselOsc, kMCG_PllClkSelPll0, &pll0Config);
98 
99 	CLOCK_SetInternalRefClkConfig(kMCG_IrclkEnable, kMCG_IrcSlow,
100 				      CONFIG_MCG_FCRDIV);
101 
102 	CLOCK_SetSimConfig(&simConfig);
103 
104 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart0))
105 	CLOCK_SetLpuartClock(LPUART0SRC_OSCERCLK);
106 #endif
107 
108 #if CONFIG_ETH_MCUX || CONFIG_ETH_NXP_ENET
109 	CLOCK_SetEnetTime0Clock(TIMESRC_OSCERCLK);
110 #endif
111 #if CONFIG_ETH_MCUX_RMII_EXT_CLK
112 	CLOCK_SetRmii0Clock(1);
113 #endif
114 #if CONFIG_USB_KINETIS || CONFIG_UDC_KINETIS
115 	CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcPll0,
116 				DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency));
117 #endif
118 }
119 
120 /**
121  *
122  * @brief Perform basic hardware initialization
123  *
124  * Initialize the interrupt controller device drivers.
125  * Also initialize the timer device driver, if required.
126  *
127  */
128 
soc_early_init_hook(void)129 void soc_early_init_hook(void)
130 {
131 #if !defined(CONFIG_ARM_MPU)
132 	uint32_t temp_reg;
133 #endif /* !CONFIG_ARM_MPU */
134 
135 	/* release I/O power hold to allow normal run state */
136 	PMC->REGSC |= PMC_REGSC_ACKISO_MASK;
137 
138 #ifdef CONFIG_TEMP_KINETIS
139 	/* enable bandgap buffer */
140 	PMC->REGSC |= PMC_REGSC_BGBE_MASK;
141 #endif /* CONFIG_TEMP_KINETIS */
142 
143 #if !defined(CONFIG_ARM_MPU)
144 	/*
145 	 * Disable memory protection and clear slave port errors.
146 	 * Note that the K64F does not implement the optional ARMv7-M memory
147 	 * protection unit (MPU), specified by the architecture (PMSAv7), in the
148 	 * Cortex-M4 core.  Instead, the processor includes its own MPU module.
149 	 */
150 	temp_reg = SYSMPU->CESR;
151 	temp_reg &= ~SYSMPU_CESR_VLD_MASK;
152 	temp_reg |= SYSMPU_CESR_SPERR_MASK;
153 	SYSMPU->CESR = temp_reg;
154 #endif /* !CONFIG_ARM_MPU */
155 
156 #ifdef CONFIG_K6X_HSRUN
157 	/* Switch to HSRUN mode */
158 	SMC->PMPROT |= SMC_PMPROT_AHSRUN_MASK;
159 	SMC->PMCTRL = (SMC->PMCTRL & ~SMC_PMCTRL_RUNM_MASK) |
160 		SMC_PMCTRL_RUNM(RUNM_HSRUN);
161 #endif
162 	/* Initialize PLL/system clock up to 180 MHz */
163 	clock_init();
164 }
165 
166 #ifdef CONFIG_SOC_RESET_HOOK
167 
soc_reset_hook(void)168 void soc_reset_hook(void)
169 {
170 	SystemInit();
171 }
172 
173 #endif /* CONFIG_SOC_RESET_HOOK */
174