1 /*
2 * Copyright 2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/init.h>
10 #include <soc.h>
11 #include <fsl_common.h>
12 #include <fsl_clock.h>
13 #include <zephyr/arch/cpu.h>
14
15 /*******************************************************************************
16 * Definitions
17 ******************************************************************************/
18 #define IRC48M_CLK_FREQ (48000000UL)
19
20 #define MCG_NODE DT_NODELABEL(mcg)
21 #define OSC_NODE DT_NODELABEL(osc)
22
23 #define SIM_MODULE_CLK_SEL_DISABLED 0U /*!< Module clock select: Disabled */
24 #define SIM_MODULE_CLK_SEL_IRC48M_CLK 1U /*!< Module clock select: IRC48M clock */
25 #define SIM_MODULE_CLK_SEL_OSCERCLK_CLK 2U /*!< Module clock select: OSCERCLK clock */
26 #define SIM_MODULE_CLK_SEL_MCGIRCLK_CLK 3U /*!< Module clock select: MCGIRCLK clock */
27
28 #define CLOCK_NODEID(clk) DT_CHILD(DT_INST(0, nxp_kinetis_sim), clk)
29
30 #define CLOCK_DIVIDER(clk) DT_PROP_OR(CLOCK_NODEID(clk), clock_div, 1) - 1
31
32 #define LPUART_CLOCK_SEL(label) \
33 (DT_PHA(DT_NODELABEL(label), clocks, name) == kCLOCK_McgIrc48MClk \
34 ? SIM_MODULE_CLK_SEL_IRC48M_CLK \
35 : DT_PHA(DT_NODELABEL(label), clocks, name) == kCLOCK_Osc0ErClk \
36 ? SIM_MODULE_CLK_SEL_OSCERCLK_CLK \
37 : DT_PHA(DT_NODELABEL(label), clocks, name) == kCLOCK_McgInternalRefClk \
38 ? SIM_MODULE_CLK_SEL_MCGIRCLK_CLK \
39 : SIM_MODULE_CLK_SEL_DISABLED)
40
41 #define TPM_CLOCK_SEL(node_id) \
42 (DT_PHA(node_id, clocks, name) == kCLOCK_McgIrc48MClk ? SIM_MODULE_CLK_SEL_IRC48M_CLK \
43 : DT_PHA(node_id, clocks, name) == kCLOCK_Osc0ErClk ? SIM_MODULE_CLK_SEL_OSCERCLK_CLK \
44 : DT_PHA(node_id, clocks, name) == kCLOCK_McgInternalRefClk \
45 ? SIM_MODULE_CLK_SEL_MCGIRCLK_CLK \
46 : SIM_MODULE_CLK_SEL_DISABLED)
47
48 /*******************************************************************************
49 * Variables
50 ******************************************************************************/
51
52 const mcglite_config_t mcgliteConfig_BOARD_BootClockRUN = {
53 .outSrc = kMCGLITE_ClkSrcHirc, /* MCGOUTCLK source is HIRC */
54 .irclkEnableMode = kMCGLITE_IrclkEnable, /* MCGIRCLK enabled */
55 .ircs = kMCGLITE_Lirc8M, /* Slow internal reference (LIRC) 8 MHz clock */
56 /* Low-frequency Reference Clock Divider */
57 .fcrdiv = DT_PROP_OR(MCG_NODE, fcrdiv, 0),
58 /* Second Low-frequency Reference Clock Divider */
59 .lircDiv2 = DT_PROP_OR(MCG_NODE, lircdiv2, 0),
60 .hircEnableInNotHircMode = true, /* HIRC source is enabled */
61 };
62
63 const sim_clock_config_t simConfig_BOARD_BootClockRUN = {
64 .er32kSrc = DT_PROP(DT_INST(0, nxp_kinetis_sim), er32k_select),
65 .clkdiv1 = SIM_CLKDIV1_OUTDIV1(CLOCK_DIVIDER(core_clk)) |
66 SIM_CLKDIV1_OUTDIV4(CLOCK_DIVIDER(flash_clk)),
67 };
68
69 const osc_config_t oscConfig_BOARD_BootClockRUN = {
70 .freq = DT_PROP(OSC_NODE, clock_frequency),
71 .capLoad = 0,
72 #if DT_ENUM_HAS_VALUE(OSC_NODE, mode, external)
73 .workMode = kOSC_ModeExt,
74 #elif DT_ENUM_HAS_VALUE(OSC_NODE, mode, low_power)
75 .workMode = kOSC_ModeOscLowPower,
76 #elif DT_ENUM_HAS_VALUE(OSC_NODE, mode, high_gain)
77 .workMode = kOSC_ModeOscHighGain,
78 #else
79 #error "An oscillator mode must be defined"
80 #endif
81 .oscerConfig = {
82 .enableMode = kOSC_ErClkEnable,
83 }
84 };
85
clock_init(void)86 static void clock_init(void)
87 {
88 /* Set the system clock dividers in SIM to safe value. */
89 CLOCK_SetSimSafeDivs();
90 /* Initializes OSC0 according to board configuration. */
91 CLOCK_InitOsc0(&oscConfig_BOARD_BootClockRUN);
92 CLOCK_SetXtal0Freq(oscConfig_BOARD_BootClockRUN.freq);
93 /* Set MCG to HIRC mode. */
94 CLOCK_SetMcgliteConfig(&mcgliteConfig_BOARD_BootClockRUN);
95 /* Set the clock configuration in SIM module. */
96 CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN);
97 /* Set SystemCoreClock variable. */
98 SystemCoreClock = DT_PROP(DT_NODELABEL(cpu0), clock_frequency);
99 /* Set LPUART0 clock source. */
100 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lpuart0))
101 CLOCK_SetLpuart0Clock(LPUART_CLOCK_SEL(lpuart0));
102 #endif
103 #if DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_tpm)
104 /* All TPM instances share common clock source for counter clock.
105 * Select the clock source using an arbitrary enabled TPM node.
106 * All TPM nodes should use the same clock source in device tree.
107 */
108 CLOCK_SetTpmClock(TPM_CLOCK_SEL(DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_kinetis_tpm)));
109 #endif
110 #if CONFIG_USB_KINETIS || CONFIG_UDC_KINETIS
111 CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcIrc48M, IRC48M_CLK_FREQ);
112 #endif
113 }
114
soc_early_init_hook(void)115 void soc_early_init_hook(void)
116 {
117 #ifdef CONFIG_TEMP_KINETIS
118 /* enable bandgap buffer */
119 PMC->REGSC |= PMC_REGSC_BGBE_MASK;
120 #endif /* CONFIG_TEMP_KINETIS */
121
122 clock_init();
123 }
124
125 #ifdef CONFIG_SOC_RESET_HOOK
126
soc_reset_hook(void)127 void soc_reset_hook(void)
128 {
129 SystemInit();
130 }
131
132 #endif /* CONFIG_SOC_RESET_HOOK */
133