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