1 /*
2 * Copyright (c) 2017, NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_kinetis_sim
8 #include <errno.h>
9 #include <soc.h>
10 #include <zephyr/drivers/clock_control.h>
11 #include <zephyr/dt-bindings/clock/kinetis_sim.h>
12 #include <fsl_clock.h>
13
14 #define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(clock_control);
17
mcux_sim_on(const struct device * dev,clock_control_subsys_t sub_system)18 static int mcux_sim_on(const struct device *dev,
19 clock_control_subsys_t sub_system)
20 {
21 clock_ip_name_t clock_ip_name = (clock_ip_name_t) sub_system;
22
23 #ifdef CONFIG_ETH_NXP_ENET
24 if ((uint32_t)sub_system == KINETIS_SIM_ENET_CLK) {
25 clock_ip_name = kCLOCK_Enet0;
26 }
27 #endif
28
29 CLOCK_EnableClock(clock_ip_name);
30
31 return 0;
32 }
33
mcux_sim_off(const struct device * dev,clock_control_subsys_t sub_system)34 static int mcux_sim_off(const struct device *dev,
35 clock_control_subsys_t sub_system)
36 {
37 clock_ip_name_t clock_ip_name = (clock_ip_name_t) sub_system;
38
39 CLOCK_DisableClock(clock_ip_name);
40
41 return 0;
42 }
43
mcux_sim_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)44 static int mcux_sim_get_subsys_rate(const struct device *dev,
45 clock_control_subsys_t sub_system,
46 uint32_t *rate)
47 {
48 clock_name_t clock_name;
49
50 switch ((uint32_t) sub_system) {
51 case KINETIS_SIM_LPO_CLK:
52 clock_name = kCLOCK_LpoClk;
53 break;
54 case KINETIS_SIM_ENET_CLK:
55 clock_name = kCLOCK_CoreSysClk;
56 break;
57 default:
58 clock_name = (clock_name_t) sub_system;
59 break;
60 }
61
62 *rate = CLOCK_GetFreq(clock_name);
63
64 return 0;
65 }
66
67 #if DT_NODE_HAS_STATUS(DT_INST(0, nxp_kinetis_ke1xf_sim), okay)
68 #define NXP_KINETIS_SIM_NODE DT_INST(0, nxp_kinetis_ke1xf_sim)
69 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_source)
70 #define NXP_KINETIS_SIM_CLKOUT_SOURCE \
71 DT_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_source)
72 #endif
73 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_divider)
74 #define NXP_KINETIS_SIM_CLKOUT_DIVIDER \
75 DT_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_divider)
76 #endif
77 #else
78 #define NXP_KINETIS_SIM_NODE DT_INST(0, nxp_kinetis_sim)
79 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_sim), clkout_source)
80 #define NXP_KINETIS_SIM_CLKOUT_SOURCE \
81 DT_PROP(DT_INST(0, nxp_kinetis_sim), clkout_source)
82 #endif
83 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_sim), clkout_divider)
84 #define NXP_KINETIS_SIM_CLKOUT_DIVIDER \
85 DT_PROP(DT_INST(0, nxp_kinetis_sim), clkout_divider)
86 #endif
87 #endif
88
mcux_sim_init(const struct device * dev)89 static int mcux_sim_init(const struct device *dev)
90 {
91 #ifdef NXP_KINETIS_SIM_CLKOUT_DIVIDER
92 SIM->CHIPCTL = (SIM->CHIPCTL & ~SIM_CHIPCTL_CLKOUTDIV_MASK)
93 | SIM_CHIPCTL_CLKOUTDIV(NXP_KINETIS_SIM_CLKOUT_DIVIDER);
94 #endif
95 #ifdef NXP_KINETIS_SIM_CLKOUT_SOURCE
96 SIM->CHIPCTL = (SIM->CHIPCTL & ~SIM_CHIPCTL_CLKOUTSEL_MASK)
97 | SIM_CHIPCTL_CLKOUTSEL(NXP_KINETIS_SIM_CLKOUT_SOURCE);
98 #endif
99
100 return 0;
101 }
102
103 static const struct clock_control_driver_api mcux_sim_driver_api = {
104 .on = mcux_sim_on,
105 .off = mcux_sim_off,
106 .get_rate = mcux_sim_get_subsys_rate,
107 };
108
109 DEVICE_DT_DEFINE(NXP_KINETIS_SIM_NODE,
110 &mcux_sim_init,
111 NULL,
112 NULL, NULL,
113 PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
114 &mcux_sim_driver_api);
115