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 	case KINETIS_SIM_ENET_1588_CLK:
58 		clock_name = kCLOCK_Osc0ErClk;
59 		break;
60 	default:
61 		clock_name = (clock_name_t) sub_system;
62 		break;
63 	}
64 
65 	*rate = CLOCK_GetFreq(clock_name);
66 
67 	return 0;
68 }
69 
70 #if DT_NODE_HAS_STATUS_OKAY(DT_INST(0, nxp_kinetis_ke1xf_sim))
71 #define NXP_KINETIS_SIM_NODE DT_INST(0, nxp_kinetis_ke1xf_sim)
72 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_source)
73 	#define NXP_KINETIS_SIM_CLKOUT_SOURCE \
74 			DT_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_source)
75 #endif
76 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_divider)
77 	#define NXP_KINETIS_SIM_CLKOUT_DIVIDER \
78 			DT_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_divider)
79 #endif
80 #else
81 #define NXP_KINETIS_SIM_NODE DT_INST(0, nxp_kinetis_sim)
82 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_sim), clkout_source)
83 	#define NXP_KINETIS_SIM_CLKOUT_SOURCE \
84 		DT_PROP(DT_INST(0, nxp_kinetis_sim), clkout_source)
85 #endif
86 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_sim), clkout_divider)
87 	#define NXP_KINETIS_SIM_CLKOUT_DIVIDER \
88 		DT_PROP(DT_INST(0, nxp_kinetis_sim), clkout_divider)
89 #endif
90 #endif
91 
mcux_sim_init(const struct device * dev)92 static int mcux_sim_init(const struct device *dev)
93 {
94 #ifdef NXP_KINETIS_SIM_CLKOUT_DIVIDER
95 	SIM->CHIPCTL = (SIM->CHIPCTL & ~SIM_CHIPCTL_CLKOUTDIV_MASK)
96 		| SIM_CHIPCTL_CLKOUTDIV(NXP_KINETIS_SIM_CLKOUT_DIVIDER);
97 #endif
98 #ifdef NXP_KINETIS_SIM_CLKOUT_SOURCE
99 	SIM->CHIPCTL = (SIM->CHIPCTL & ~SIM_CHIPCTL_CLKOUTSEL_MASK)
100 		| SIM_CHIPCTL_CLKOUTSEL(NXP_KINETIS_SIM_CLKOUT_SOURCE);
101 #endif
102 
103 	return 0;
104 }
105 
106 static DEVICE_API(clock_control, mcux_sim_driver_api) = {
107 	.on = mcux_sim_on,
108 	.off = mcux_sim_off,
109 	.get_rate = mcux_sim_get_subsys_rate,
110 };
111 
112 DEVICE_DT_DEFINE(NXP_KINETIS_SIM_NODE,
113 		    mcux_sim_init,
114 		    NULL,
115 		    NULL, NULL,
116 		    PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
117 		    &mcux_sim_driver_api);
118