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