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 	CLOCK_EnableClock(clock_ip_name);
24 
25 	return 0;
26 }
27 
mcux_sim_off(const struct device * dev,clock_control_subsys_t sub_system)28 static int mcux_sim_off(const struct device *dev,
29 			clock_control_subsys_t sub_system)
30 {
31 	clock_ip_name_t clock_ip_name = (clock_ip_name_t) sub_system;
32 
33 	CLOCK_DisableClock(clock_ip_name);
34 
35 	return 0;
36 }
37 
mcux_sim_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)38 static int mcux_sim_get_subsys_rate(const struct device *dev,
39 				    clock_control_subsys_t sub_system,
40 				    uint32_t *rate)
41 {
42 	clock_name_t clock_name;
43 
44 	switch ((uint32_t) sub_system) {
45 	case KINETIS_SIM_LPO_CLK:
46 		clock_name = kCLOCK_LpoClk;
47 		break;
48 	default:
49 		clock_name = (clock_name_t) sub_system;
50 		break;
51 	}
52 
53 	*rate = CLOCK_GetFreq(clock_name);
54 
55 	return 0;
56 }
57 
58 #if DT_NODE_HAS_STATUS(DT_INST(0, nxp_kinetis_ke1xf_sim), okay)
59 #define NXP_KINETIS_SIM_NODE DT_INST(0, nxp_kinetis_ke1xf_sim)
60 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_source)
61 	#define NXP_KINETIS_SIM_CLKOUT_SOURCE \
62 			DT_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_source)
63 #endif
64 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_divider)
65 	#define NXP_KINETIS_SIM_CLKOUT_DIVIDER \
66 			DT_PROP(DT_INST(0, nxp_kinetis_ke1xf_sim), clkout_divider)
67 #endif
68 #else
69 #define NXP_KINETIS_SIM_NODE DT_INST(0, nxp_kinetis_sim)
70 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_sim), clkout_source)
71 	#define NXP_KINETIS_SIM_CLKOUT_SOURCE \
72 		DT_PROP(DT_INST(0, nxp_kinetis_sim), clkout_source)
73 #endif
74 #if DT_NODE_HAS_PROP(DT_INST(0, nxp_kinetis_sim), clkout_divider)
75 	#define NXP_KINETIS_SIM_CLKOUT_DIVIDER \
76 		DT_PROP(DT_INST(0, nxp_kinetis_sim), clkout_divider)
77 #endif
78 #endif
79 
mcux_sim_init(const struct device * dev)80 static int mcux_sim_init(const struct device *dev)
81 {
82 #ifdef NXP_KINETIS_SIM_CLKOUT_DIVIDER
83 	SIM->CHIPCTL = (SIM->CHIPCTL & ~SIM_CHIPCTL_CLKOUTDIV_MASK)
84 		| SIM_CHIPCTL_CLKOUTDIV(NXP_KINETIS_SIM_CLKOUT_DIVIDER);
85 #endif
86 #ifdef NXP_KINETIS_SIM_CLKOUT_SOURCE
87 	SIM->CHIPCTL = (SIM->CHIPCTL & ~SIM_CHIPCTL_CLKOUTSEL_MASK)
88 		| SIM_CHIPCTL_CLKOUTSEL(NXP_KINETIS_SIM_CLKOUT_SOURCE);
89 #endif
90 
91 	return 0;
92 }
93 
94 static const struct clock_control_driver_api mcux_sim_driver_api = {
95 	.on = mcux_sim_on,
96 	.off = mcux_sim_off,
97 	.get_rate = mcux_sim_get_subsys_rate,
98 };
99 
100 DEVICE_DT_DEFINE(NXP_KINETIS_SIM_NODE,
101 		    &mcux_sim_init,
102 		    NULL,
103 		    NULL, NULL,
104 		    PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
105 		    &mcux_sim_driver_api);
106