1 /*
2  * Copyright (c) 2020-23, NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_lpc_syscon
8 #include <errno.h>
9 #include <zephyr/drivers/clock_control.h>
10 #include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
11 #include <soc.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_lpc_syscon_clock_control_on(const struct device * dev,clock_control_subsys_t sub_system)18 static int mcux_lpc_syscon_clock_control_on(const struct device *dev,
19 			      clock_control_subsys_t sub_system)
20 {
21 #if defined(CONFIG_CAN_MCUX_MCAN)
22 	if ((uint32_t)sub_system == MCUX_MCAN_CLK) {
23 		CLOCK_EnableClock(kCLOCK_Mcan);
24 	}
25 #endif /* defined(CONFIG_CAN_MCUX_MCAN) */
26 #if defined(CONFIG_COUNTER_NXP_MRT)
27 	if ((uint32_t)sub_system == MCUX_MRT_CLK) {
28 #if defined(CONFIG_SOC_FAMILY_LPC)
29 		CLOCK_EnableClock(kCLOCK_Mrt);
30 #elif defined(CONFIG_SOC_FAMILY_IMX)
31 		CLOCK_EnableClock(kCLOCK_Mrt0);
32 #endif
33 	}
34 #endif /* defined(CONFIG_COUNTER_NXP_MRT) */
35 
36 	return 0;
37 }
38 
mcux_lpc_syscon_clock_control_off(const struct device * dev,clock_control_subsys_t sub_system)39 static int mcux_lpc_syscon_clock_control_off(const struct device *dev,
40 			       clock_control_subsys_t sub_system)
41 {
42 	return 0;
43 }
44 
mcux_lpc_syscon_clock_control_get_subsys_rate(const struct device * dev,clock_control_subsys_t sub_system,uint32_t * rate)45 static int mcux_lpc_syscon_clock_control_get_subsys_rate(
46 					const struct device *dev,
47 				    clock_control_subsys_t sub_system,
48 				    uint32_t *rate)
49 {
50 	uint32_t clock_name = (uint32_t) sub_system;
51 
52 	switch (clock_name) {
53 
54 #if defined(CONFIG_I2C_MCUX_FLEXCOMM) || \
55 		defined(CONFIG_SPI_MCUX_FLEXCOMM) || \
56 		defined(CONFIG_UART_MCUX_FLEXCOMM)
57 	case MCUX_FLEXCOMM0_CLK:
58 		*rate = CLOCK_GetFlexCommClkFreq(0);
59 		break;
60 	case MCUX_FLEXCOMM1_CLK:
61 		*rate = CLOCK_GetFlexCommClkFreq(1);
62 		break;
63 	case MCUX_FLEXCOMM2_CLK:
64 		*rate = CLOCK_GetFlexCommClkFreq(2);
65 		break;
66 	case MCUX_FLEXCOMM3_CLK:
67 		*rate = CLOCK_GetFlexCommClkFreq(3);
68 		break;
69 	case MCUX_FLEXCOMM4_CLK:
70 		*rate = CLOCK_GetFlexCommClkFreq(4);
71 		break;
72 	case MCUX_FLEXCOMM5_CLK:
73 		*rate = CLOCK_GetFlexCommClkFreq(5);
74 		break;
75 	case MCUX_FLEXCOMM6_CLK:
76 		*rate = CLOCK_GetFlexCommClkFreq(6);
77 		break;
78 	case MCUX_FLEXCOMM7_CLK:
79 		*rate = CLOCK_GetFlexCommClkFreq(7);
80 		break;
81 	case MCUX_FLEXCOMM8_CLK:
82 		*rate = CLOCK_GetFlexCommClkFreq(8);
83 		break;
84 	case MCUX_FLEXCOMM9_CLK:
85 		*rate = CLOCK_GetFlexCommClkFreq(9);
86 		break;
87 	case MCUX_FLEXCOMM10_CLK:
88 		*rate = CLOCK_GetFlexCommClkFreq(10);
89 		break;
90 	case MCUX_FLEXCOMM11_CLK:
91 		*rate = CLOCK_GetFlexCommClkFreq(11);
92 		break;
93 	case MCUX_FLEXCOMM12_CLK:
94 		*rate = CLOCK_GetFlexCommClkFreq(12);
95 		break;
96 	case MCUX_FLEXCOMM13_CLK:
97 		*rate = CLOCK_GetFlexCommClkFreq(13);
98 		break;
99 	case MCUX_PMIC_I2C_CLK:
100 		*rate = CLOCK_GetFlexCommClkFreq(15);
101 		break;
102 	case MCUX_HS_SPI_CLK:
103 #if defined(SYSCON_HSLSPICLKSEL_SEL_MASK)
104 		*rate = CLOCK_GetHsLspiClkFreq();
105 #else
106 		*rate = CLOCK_GetFlexCommClkFreq(14);
107 #endif
108 		break;
109 	case MCUX_HS_SPI1_CLK:
110 		*rate = CLOCK_GetFlexCommClkFreq(16);
111 		break;
112 #endif
113 
114 #if (defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT)
115 	case MCUX_USDHC1_CLK:
116 		*rate = CLOCK_GetSdioClkFreq(0);
117 		break;
118 	case MCUX_USDHC2_CLK:
119 		*rate = CLOCK_GetSdioClkFreq(1);
120 		break;
121 #endif
122 
123 #if (defined(FSL_FEATURE_SOC_SDIF_COUNT) && \
124 	(FSL_FEATURE_SOC_SDIF_COUNT)) && \
125 	CONFIG_MCUX_SDIF
126 	case MCUX_SDIF_CLK:
127 		*rate = CLOCK_GetSdioClkFreq();
128 		break;
129 #endif
130 
131 #if defined(CONFIG_CAN_MCUX_MCAN)
132 	case MCUX_MCAN_CLK:
133 		*rate = CLOCK_GetMCanClkFreq();
134 		break;
135 #endif /* defined(CONFIG_CAN_MCUX_MCAN) */
136 
137 #if defined(CONFIG_COUNTER_MCUX_CTIMER) || defined(CONFIG_PWM_MCUX_CTIMER)
138 	case (MCUX_CTIMER0_CLK + MCUX_CTIMER_CLK_OFFSET):
139 		*rate = CLOCK_GetCTimerClkFreq(0);
140 		break;
141 	case (MCUX_CTIMER1_CLK + MCUX_CTIMER_CLK_OFFSET):
142 		*rate = CLOCK_GetCTimerClkFreq(1);
143 		break;
144 	case (MCUX_CTIMER2_CLK + MCUX_CTIMER_CLK_OFFSET):
145 		*rate = CLOCK_GetCTimerClkFreq(2);
146 		break;
147 	case (MCUX_CTIMER3_CLK + MCUX_CTIMER_CLK_OFFSET):
148 		*rate = CLOCK_GetCTimerClkFreq(3);
149 		break;
150 	case (MCUX_CTIMER4_CLK + MCUX_CTIMER_CLK_OFFSET):
151 		*rate = CLOCK_GetCTimerClkFreq(4);
152 		break;
153 #endif
154 
155 #if defined(CONFIG_COUNTER_NXP_MRT)
156 	case MCUX_MRT_CLK:
157 #endif
158 #if defined(CONFIG_PWM_MCUX_SCTIMER)
159 	case MCUX_SCTIMER_CLK:
160 #endif
161 	case MCUX_BUS_CLK:
162 		*rate = CLOCK_GetFreq(kCLOCK_BusClk);
163 		break;
164 
165 #if defined(CONFIG_I3C_MCUX)
166 	case MCUX_I3C_CLK:
167 		*rate = CLOCK_GetI3cClkFreq();
168 		break;
169 #endif
170 
171 #if defined(CONFIG_MIPI_DSI_MCUX_2L)
172 	case MCUX_MIPI_DSI_DPHY_CLK:
173 		*rate = CLOCK_GetMipiDphyClkFreq();
174 		break;
175 	case MCUX_MIPI_DSI_ESC_CLK:
176 		*rate = CLOCK_GetMipiDphyEscTxClkFreq();
177 		break;
178 	case MCUX_LCDIF_PIXEL_CLK:
179 		*rate = CLOCK_GetDcPixelClkFreq();
180 		break;
181 #endif
182 #if defined(CONFIG_AUDIO_DMIC_MCUX)
183 	case MCUX_DMIC_CLK:
184 		*rate = CLOCK_GetDmicClkFreq();
185 		break;
186 #endif
187 	}
188 
189 	return 0;
190 }
191 
192 static const struct clock_control_driver_api mcux_lpc_syscon_api = {
193 	.on = mcux_lpc_syscon_clock_control_on,
194 	.off = mcux_lpc_syscon_clock_control_off,
195 	.get_rate = mcux_lpc_syscon_clock_control_get_subsys_rate,
196 };
197 
198 #define LPC_CLOCK_INIT(n) \
199 	\
200 DEVICE_DT_INST_DEFINE(n, \
201 		    NULL, \
202 		    NULL, \
203 		    NULL, NULL, \
204 		    PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \
205 		    &mcux_lpc_syscon_api);
206 
207 DT_INST_FOREACH_STATUS_OKAY(LPC_CLOCK_INIT)
208