1 /*
2 * Copyright (c) 2019 STMicroelectronics
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <soc.h>
8 #include <stm32_ll_bus.h>
9 #include <stm32_ll_rcc.h>
10 #include <zephyr/drivers/clock_control.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
13
14 /**
15 * @brief fill in AHB/APB buses configuration structure
16 */
stm32_clock_control_on(const struct device * dev,clock_control_subsys_t sub_system)17 static inline int stm32_clock_control_on(const struct device *dev,
18 clock_control_subsys_t sub_system)
19 {
20 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
21
22 ARG_UNUSED(dev);
23
24 switch (pclken->bus) {
25 case STM32_CLOCK_BUS_APB1:
26 LL_APB1_GRP1_EnableClock(pclken->enr);
27 break;
28 case STM32_CLOCK_BUS_APB2:
29 LL_APB2_GRP1_EnableClock(pclken->enr);
30 break;
31 case STM32_CLOCK_BUS_APB3:
32 LL_APB3_GRP1_EnableClock(pclken->enr);
33 break;
34 case STM32_CLOCK_BUS_APB4:
35 LL_APB4_GRP1_EnableClock(pclken->enr);
36 break;
37 case STM32_CLOCK_BUS_APB5:
38 LL_APB5_GRP1_EnableClock(pclken->enr);
39 break;
40 case STM32_CLOCK_BUS_AHB2:
41 LL_AHB2_GRP1_EnableClock(pclken->enr);
42 break;
43 case STM32_CLOCK_BUS_AHB3:
44 LL_AHB3_GRP1_EnableClock(pclken->enr);
45 break;
46 case STM32_CLOCK_BUS_AHB4:
47 LL_AHB4_GRP1_EnableClock(pclken->enr);
48 break;
49 case STM32_CLOCK_BUS_AHB5:
50 LL_AHB5_GRP1_EnableClock(pclken->enr);
51 break;
52 case STM32_CLOCK_BUS_AHB6:
53 LL_AHB6_GRP1_EnableClock(pclken->enr);
54 break;
55 case STM32_CLOCK_BUS_AXI:
56 LL_AXI_GRP1_EnableClock(pclken->enr);
57 break;
58 case STM32_CLOCK_BUS_MLAHB:
59 LL_MLAHB_GRP1_EnableClock(pclken->enr);
60 break;
61 default:
62 return -ENOTSUP;
63 }
64
65 return 0;
66 }
67
stm32_clock_control_off(const struct device * dev,clock_control_subsys_t sub_system)68 static inline int stm32_clock_control_off(const struct device *dev,
69 clock_control_subsys_t sub_system)
70 {
71 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
72
73 ARG_UNUSED(dev);
74
75 switch (pclken->bus) {
76 case STM32_CLOCK_BUS_APB1:
77 LL_APB1_GRP1_DisableClock(pclken->enr);
78 break;
79 case STM32_CLOCK_BUS_APB2:
80 LL_APB2_GRP1_DisableClock(pclken->enr);
81 break;
82 case STM32_CLOCK_BUS_APB3:
83 LL_APB3_GRP1_DisableClock(pclken->enr);
84 break;
85 case STM32_CLOCK_BUS_APB4:
86 LL_APB4_GRP1_DisableClock(pclken->enr);
87 break;
88 case STM32_CLOCK_BUS_APB5:
89 LL_APB5_GRP1_DisableClock(pclken->enr);
90 break;
91 case STM32_CLOCK_BUS_AHB2:
92 LL_AHB2_GRP1_DisableClock(pclken->enr);
93 break;
94 case STM32_CLOCK_BUS_AHB3:
95 LL_AHB3_GRP1_DisableClock(pclken->enr);
96 break;
97 case STM32_CLOCK_BUS_AHB4:
98 LL_AHB4_GRP1_DisableClock(pclken->enr);
99 break;
100 case STM32_CLOCK_BUS_AHB5:
101 LL_AHB5_GRP1_DisableClock(pclken->enr);
102 break;
103 case STM32_CLOCK_BUS_AHB6:
104 LL_AHB6_GRP1_DisableClock(pclken->enr);
105 break;
106 case STM32_CLOCK_BUS_AXI:
107 LL_AXI_GRP1_DisableClock(pclken->enr);
108 break;
109 case STM32_CLOCK_BUS_MLAHB:
110 LL_MLAHB_GRP1_DisableClock(pclken->enr);
111 break;
112 default:
113 return -ENOTSUP;
114 }
115
116 return 0;
117 }
118
stm32_clock_control_get_subsys_rate(const struct device * clock,clock_control_subsys_t sub_system,uint32_t * rate)119 static int stm32_clock_control_get_subsys_rate(const struct device *clock,
120 clock_control_subsys_t sub_system,
121 uint32_t *rate)
122 {
123 struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system);
124
125 ARG_UNUSED(clock);
126
127 switch (pclken->bus) {
128 case STM32_CLOCK_BUS_APB1:
129 switch (pclken->enr) {
130 case LL_APB1_GRP1_PERIPH_TIM2:
131 case LL_APB1_GRP1_PERIPH_TIM3:
132 case LL_APB1_GRP1_PERIPH_TIM4:
133 case LL_APB1_GRP1_PERIPH_TIM5:
134 case LL_APB1_GRP1_PERIPH_TIM6:
135 case LL_APB1_GRP1_PERIPH_TIM7:
136 case LL_APB1_GRP1_PERIPH_TIM12:
137 case LL_APB1_GRP1_PERIPH_TIM13:
138 case LL_APB1_GRP1_PERIPH_TIM14:
139 *rate = LL_RCC_GetTIMGClockFreq(LL_RCC_TIMG1PRES);
140 break;
141 case LL_APB1_GRP1_PERIPH_LPTIM1:
142 *rate = LL_RCC_GetLPTIMClockFreq(
143 LL_RCC_LPTIM1_CLKSOURCE);
144 break;
145 case LL_APB1_GRP1_PERIPH_SPI2:
146 case LL_APB1_GRP1_PERIPH_SPI3:
147 *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI23_CLKSOURCE);
148 break;
149 case LL_APB1_GRP1_PERIPH_USART2:
150 case LL_APB1_GRP1_PERIPH_UART4:
151 *rate = LL_RCC_GetUARTClockFreq(
152 LL_RCC_UART24_CLKSOURCE);
153 break;
154 case LL_APB1_GRP1_PERIPH_USART3:
155 case LL_APB1_GRP1_PERIPH_UART5:
156 *rate = LL_RCC_GetUARTClockFreq(
157 LL_RCC_UART35_CLKSOURCE);
158 break;
159 case LL_APB1_GRP1_PERIPH_UART7:
160 case LL_APB1_GRP1_PERIPH_UART8:
161 *rate = LL_RCC_GetUARTClockFreq(
162 LL_RCC_UART78_CLKSOURCE);
163 break;
164 case LL_APB1_GRP1_PERIPH_I2C1:
165 case LL_APB1_GRP1_PERIPH_I2C2:
166 *rate = LL_RCC_GetI2CClockFreq(LL_RCC_I2C12_CLKSOURCE);
167 break;
168 case LL_APB1_GRP1_PERIPH_I2C3:
169 case LL_APB1_GRP1_PERIPH_I2C5:
170 *rate = LL_RCC_GetI2CClockFreq(LL_RCC_I2C35_CLKSOURCE);
171 break;
172 case LL_APB1_GRP1_PERIPH_SPDIF:
173 *rate = LL_RCC_GetSPDIFRXClockFreq(
174 LL_RCC_SPDIFRX_CLKSOURCE);
175 break;
176 case LL_APB1_GRP1_PERIPH_CEC:
177 *rate = LL_RCC_GetCECClockFreq(LL_RCC_CEC_CLKSOURCE);
178 break;
179 case LL_APB1_GRP1_PERIPH_WWDG1:
180 case LL_APB1_GRP1_PERIPH_DAC12:
181 case LL_APB1_GRP1_PERIPH_MDIOS:
182 default:
183 return -ENOTSUP;
184 }
185 break;
186 case STM32_CLOCK_BUS_APB2:
187 switch (pclken->enr) {
188 case LL_APB2_GRP1_PERIPH_TIM1:
189 case LL_APB2_GRP1_PERIPH_TIM8:
190 case LL_APB2_GRP1_PERIPH_TIM15:
191 case LL_APB2_GRP1_PERIPH_TIM16:
192 case LL_APB2_GRP1_PERIPH_TIM17:
193 *rate = LL_RCC_GetTIMGClockFreq(LL_RCC_TIMG2PRES);
194 break;
195 case LL_APB2_GRP1_PERIPH_SPI1:
196 *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI1_CLKSOURCE);
197 break;
198 case LL_APB2_GRP1_PERIPH_SPI4:
199 case LL_APB2_GRP1_PERIPH_SPI5:
200 *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI45_CLKSOURCE);
201 break;
202 case LL_APB2_GRP1_PERIPH_USART6:
203 *rate = LL_RCC_GetUARTClockFreq(
204 LL_RCC_USART6_CLKSOURCE);
205 break;
206 case LL_APB2_GRP1_PERIPH_SAI1:
207 *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI1_CLKSOURCE);
208 break;
209 case LL_APB2_GRP1_PERIPH_SAI2:
210 *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI2_CLKSOURCE);
211 break;
212 case LL_APB2_GRP1_PERIPH_SAI3:
213 *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI3_CLKSOURCE);
214 break;
215 case LL_APB2_GRP1_PERIPH_DFSDM1:
216 *rate = LL_RCC_GetDFSDMClockFreq(
217 LL_RCC_DFSDM_CLKSOURCE);
218 break;
219 case LL_APB2_GRP1_PERIPH_FDCAN:
220 *rate = LL_RCC_GetFDCANClockFreq(
221 LL_RCC_FDCAN_CLKSOURCE);
222 break;
223 case LL_APB2_GRP1_PERIPH_ADFSDM1:
224 default:
225 return -ENOTSUP;
226 }
227 break;
228 case STM32_CLOCK_BUS_APB3:
229 switch (pclken->enr) {
230 case LL_APB3_GRP1_PERIPH_LPTIM2:
231 case LL_APB3_GRP1_PERIPH_LPTIM3:
232 *rate = LL_RCC_GetLPTIMClockFreq(
233 LL_RCC_LPTIM23_CLKSOURCE);
234 break;
235 case LL_APB3_GRP1_PERIPH_LPTIM4:
236 case LL_APB3_GRP1_PERIPH_LPTIM5:
237 *rate = LL_RCC_GetLPTIMClockFreq(
238 LL_RCC_LPTIM45_CLKSOURCE);
239 break;
240 case LL_APB3_GRP1_PERIPH_SAI4:
241 *rate = LL_RCC_GetSAIClockFreq(LL_RCC_SAI4_CLKSOURCE);
242 break;
243 case LL_APB3_GRP1_PERIPH_SYSCFG:
244 case LL_APB3_GRP1_PERIPH_VREF:
245 case LL_APB3_GRP1_PERIPH_TMPSENS:
246 case LL_APB3_GRP1_PERIPH_HDP:
247 default:
248 return -ENOTSUP;
249 }
250 break;
251 case STM32_CLOCK_BUS_APB4:
252 switch (pclken->enr) {
253 case LL_APB4_GRP1_PERIPH_LTDC:
254 *rate = LL_RCC_GetLTDCClockFreq();
255 break;
256 case LL_APB4_GRP1_PERIPH_DSI:
257 *rate = LL_RCC_GetDSIClockFreq(LL_RCC_DSI_CLKSOURCE);
258 break;
259 case LL_APB4_GRP1_PERIPH_USBPHY:
260 *rate = LL_RCC_GetUSBPHYClockFreq(
261 LL_RCC_USBPHY_CLKSOURCE);
262 break;
263 case LL_APB4_GRP1_PERIPH_DDRPERFM:
264 case LL_APB4_GRP1_PERIPH_STGENRO:
265 case LL_APB4_GRP1_PERIPH_STGENROSTP:
266 default:
267 return -ENOTSUP;
268 }
269 break;
270 case STM32_CLOCK_BUS_APB5:
271 switch (pclken->enr) {
272 case LL_APB5_GRP1_PERIPH_SPI6:
273 *rate = LL_RCC_GetSPIClockFreq(LL_RCC_SPI6_CLKSOURCE);
274 break;
275 case LL_APB5_GRP1_PERIPH_I2C4:
276 case LL_APB5_GRP1_PERIPH_I2C6:
277 *rate = LL_RCC_GetI2CClockFreq(LL_RCC_I2C46_CLKSOURCE);
278 break;
279 case LL_APB5_GRP1_PERIPH_USART1:
280 *rate = LL_RCC_GetUARTClockFreq(
281 LL_RCC_USART1_CLKSOURCE);
282 break;
283 case LL_APB5_GRP1_PERIPH_STGEN:
284 case LL_APB5_GRP1_PERIPH_STGENSTP:
285 *rate = LL_RCC_GetSTGENClockFreq(
286 LL_RCC_STGEN_CLKSOURCE);
287 break;
288 case LL_APB5_GRP1_PERIPH_RTCAPB:
289 *rate = LL_RCC_GetRTCClockFreq();
290 break;
291 case LL_APB5_GRP1_PERIPH_TZC1:
292 case LL_APB5_GRP1_PERIPH_TZC2:
293 case LL_APB5_GRP1_PERIPH_TZPC:
294 case LL_APB5_GRP1_PERIPH_BSEC:
295 default:
296 return -ENOTSUP;
297 }
298 break;
299 case STM32_CLOCK_BUS_AHB2:
300 switch (pclken->enr) {
301 case LL_AHB2_GRP1_PERIPH_ADC12:
302 *rate = LL_RCC_GetADCClockFreq(LL_RCC_ADC_CLKSOURCE);
303 break;
304 case LL_AHB2_GRP1_PERIPH_USBO:
305 *rate = LL_RCC_GetUSBOClockFreq(LL_RCC_USBO_CLKSOURCE);
306 break;
307 case LL_AHB2_GRP1_PERIPH_SDMMC3:
308 *rate = LL_RCC_GetSDMMCClockFreq(
309 LL_RCC_SDMMC3_CLKSOURCE);
310 break;
311 case LL_AHB2_GRP1_PERIPH_DMA1:
312 case LL_AHB2_GRP1_PERIPH_DMA2:
313 case LL_AHB2_GRP1_PERIPH_DMAMUX:
314 default:
315 return -ENOTSUP;
316 }
317 break;
318 case STM32_CLOCK_BUS_AHB3:
319 switch (pclken->enr) {
320 case LL_AHB3_GRP1_PERIPH_RNG2:
321 *rate = LL_RCC_GetRNGClockFreq(LL_RCC_RNG2_CLKSOURCE);
322 break;
323 case LL_AHB3_GRP1_PERIPH_DCMI:
324 case LL_AHB3_GRP1_PERIPH_CRYP2:
325 case LL_AHB3_GRP1_PERIPH_HASH2:
326 case LL_AHB3_GRP1_PERIPH_CRC2:
327 case LL_AHB3_GRP1_PERIPH_HSEM:
328 case LL_AHB3_GRP1_PERIPH_IPCC:
329 default:
330 return -ENOTSUP;
331 }
332 break;
333 case STM32_CLOCK_BUS_AHB4:
334 return -ENOTSUP;
335 case STM32_CLOCK_BUS_AHB5:
336 switch (pclken->enr) {
337 case LL_AHB5_GRP1_PERIPH_RNG1:
338 *rate = LL_RCC_GetRNGClockFreq(LL_RCC_RNG1_CLKSOURCE);
339 break;
340 case LL_AHB5_GRP1_PERIPH_GPIOZ:
341 case LL_AHB5_GRP1_PERIPH_CRYP1:
342 case LL_AHB5_GRP1_PERIPH_HASH1:
343 case LL_AHB5_GRP1_PERIPH_BKPSRAM:
344 default:
345 return -ENOTSUP;
346 }
347 break;
348 case STM32_CLOCK_BUS_AHB6:
349 switch (pclken->enr) {
350 case LL_AHB6_GRP1_PERIPH_ETH1CK:
351 case LL_AHB6_GRP1_PERIPH_ETH1TX:
352 case LL_AHB6_GRP1_PERIPH_ETH1RX:
353 case LL_AHB6_GRP1_PERIPH_ETH1MAC:
354 case LL_AHB6_GRP1_PERIPH_ETH1STP:
355 *rate = LL_RCC_GetETHClockFreq(LL_RCC_ETH_CLKSOURCE);
356 break;
357 case LL_AHB6_GRP1_PERIPH_FMC:
358 *rate = LL_RCC_GetFMCClockFreq(LL_RCC_FMC_CLKSOURCE);
359 break;
360 case LL_AHB6_GRP1_PERIPH_QSPI:
361 *rate = LL_RCC_GetQSPIClockFreq(LL_RCC_QSPI_CLKSOURCE);
362 break;
363 case LL_AHB6_GRP1_PERIPH_SDMMC1:
364 case LL_AHB6_GRP1_PERIPH_SDMMC2:
365 *rate = LL_RCC_GetSDMMCClockFreq(
366 LL_RCC_SDMMC12_CLKSOURCE);
367 break;
368 case LL_AHB6_GRP1_PERIPH_MDMA:
369 case LL_AHB6_GRP1_PERIPH_GPU:
370 case LL_AHB6_GRP1_PERIPH_CRC1:
371 case LL_AHB6_GRP1_PERIPH_USBH:
372 default:
373 return -ENOTSUP;
374 }
375 break;
376 case STM32_CLOCK_BUS_AXI:
377 switch (pclken->enr) {
378 case LL_AXI_GRP1_PERIPH_SYSRAMEN:
379 default:
380 return -ENOTSUP;
381 }
382 break;
383 case STM32_CLOCK_BUS_MLAHB:
384 switch (pclken->enr) {
385 case LL_MLAHB_GRP1_PERIPH_RETRAMEN:
386 default:
387 return -ENOTSUP;
388 }
389 break;
390 default:
391 return -ENOTSUP;
392 }
393 return 0;
394 }
395
396 static struct clock_control_driver_api stm32_clock_control_api = {
397 .on = stm32_clock_control_on,
398 .off = stm32_clock_control_off,
399 .get_rate = stm32_clock_control_get_subsys_rate,
400 };
401
stm32_clock_control_init(const struct device * dev)402 static int stm32_clock_control_init(const struct device *dev)
403 {
404 ARG_UNUSED(dev);
405 return 0;
406 }
407
408 /**
409 * @brief RCC device, note that priority is intentionally set to 1 so
410 * that the device init runs just after SOC init
411 */
412 DEVICE_DT_DEFINE(DT_NODELABEL(rcc),
413 &stm32_clock_control_init,
414 NULL,
415 NULL, NULL,
416 PRE_KERNEL_1,
417 CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
418 &stm32_clock_control_api);
419