1 /*!
2 \file gd32vf103_rcu.c
3 \brief RCU driver
4
5 \version 2019-6-5, V1.0.0, firmware for GD32VF103
6 */
7
8 /*
9 Copyright (c) 2019, GigaDevice Semiconductor Inc.
10
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13
14 1. Redistributions of source code must retain the above copyright notice, this
15 list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 3. Neither the name of the copyright holder nor the names of its contributors
20 may be used to endorse or promote products derived from this software without
21 specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34
35 #include "gd32vf103_rcu.h"
36
37
38 /*!
39 \brief deinitialize the RCU
40 \param[in] none
41 \param[out] none
42 \retval none
43 */
rcu_deinit(void)44 void rcu_deinit(void)
45 {
46 /* enable IRC8M */
47 RCU_CTL |= RCU_CTL_IRC8MEN;
48 rcu_osci_stab_wait(RCU_IRC8M);
49
50 /* reset CFG0 register */
51 RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
52 RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
53 RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4);
54 /* reset CTL register */
55 RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
56 RCU_CTL &= ~RCU_CTL_HXTALBPS;
57 RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN);
58 /* reset INT and CFG1 register */
59 RCU_INT = 0x00ff0000U;
60 RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF |
61 RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL);
62 }
63
64 /*!
65 \brief enable the peripherals clock
66 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
67 only one parameter can be selected which is shown as below:
68 \arg RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock
69 \arg RCU_AF : alternate function clock
70 \arg RCU_CRC: CRC clock
71 \arg RCU_DMAx (x=0,1): DMA clock
72 \arg RCU_USBFS: USBFS clock
73 \arg RCU_EXMC: EXMC clock
74 \arg RCU_TIMERx (x=0,1,2,3,4,5,6): TIMER clock
75 \arg RCU_WWDGT: WWDGT clock
76 \arg RCU_SPIx (x=0,1,2): SPI clock
77 \arg RCU_USARTx (x=0,1,2): USART clock
78 \arg RCU_UARTx (x=3,4): UART clock
79 \arg RCU_I2Cx (x=0,1): I2C clock
80 \arg RCU_CANx (x=0,1): CAN clock
81 \arg RCU_PMU: PMU clock
82 \arg RCU_DAC: DAC clock
83 \arg RCU_RTC: RTC clock
84 \arg RCU_ADCx (x=0,1): ADC clock
85 \arg RCU_BKPI: BKP interface clock
86 \param[out] none
87 \retval none
88 */
rcu_periph_clock_enable(rcu_periph_enum periph)89 void rcu_periph_clock_enable(rcu_periph_enum periph)
90 {
91 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
92 }
93
94 /*!
95 \brief disable the peripherals clock
96 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
97 only one parameter can be selected which is shown as below:
98 \arg RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock
99 \arg RCU_AF: alternate function clock
100 \arg RCU_CRC: CRC clock
101 \arg RCU_DMAx (x=0,1): DMA clock
102 \arg RCU_USBFS: USBFS clock
103 \arg RCU_EXMC: EXMC clock
104 \arg RCU_TIMERx (x=0,1,2,3,4,5,6): TIMER clock
105 \arg RCU_WWDGT: WWDGT clock
106 \arg RCU_SPIx (x=0,1,2): SPI clock
107 \arg RCU_USARTx (x=0,1,2): USART clock
108 \arg RCU_UARTx (x=3,4): UART clock
109 \arg RCU_I2Cx (x=0,1): I2C clock
110 \arg RCU_CANx (x=0,1): CAN clock
111 \arg RCU_PMU: PMU clock
112 \arg RCU_DAC: DAC clock
113 \arg RCU_RTC: RTC clock
114 \arg RCU_ADCx (x=0,1): ADC clock
115 \arg RCU_BKPI: BKP interface clock
116 \param[out] none
117 \retval none
118 */
rcu_periph_clock_disable(rcu_periph_enum periph)119 void rcu_periph_clock_disable(rcu_periph_enum periph)
120 {
121 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
122 }
123
124 /*!
125 \brief enable the peripherals clock when sleep mode
126 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
127 only one parameter can be selected which is shown as below:
128 \arg RCU_FMC_SLP: FMC clock
129 \arg RCU_SRAM_SLP: SRAM clock
130 \param[out] none
131 \retval none
132 */
rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)133 void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
134 {
135 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
136 }
137
138 /*!
139 \brief disable the peripherals clock when sleep mode
140 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
141 only one parameter can be selected which is shown as below:
142 \arg RCU_FMC_SLP: FMC clock
143 \arg RCU_SRAM_SLP: SRAM clock
144 \param[out] none
145 \retval none
146 */
rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)147 void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
148 {
149 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
150 }
151
152 /*!
153 \brief reset the peripherals
154 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
155 only one parameter can be selected which is shown as below:
156 \arg RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports
157 \arg RCU_AFRST : reset alternate function clock
158 \arg RCU_USBFSRST: reset USBFS
159 \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6): reset TIMER
160 \arg RCU_WWDGTRST: reset WWDGT
161 \arg RCU_SPIxRST (x=0,1,2): reset SPI
162 \arg RCU_USARTxRST (x=0,1,2): reset USART
163 \arg RCU_UARTxRST (x=3,4): reset UART
164 \arg RCU_I2CxRST (x=0,1): reset I2C
165 \arg RCU_CANxRST (x=0,1): reset CAN
166 \arg RCU_PMURST: reset PMU
167 \arg RCU_DACRST: reset DAC
168 \arg RCU_ADCxRST (x=0,1): reset ADC
169 \arg RCU_BKPIRST: reset BKPI
170 \param[out] none
171 \retval none
172 */
rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)173 void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
174 {
175 RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
176 }
177
178 /*!
179 \brief disable reset the peripheral
180 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
181 only one parameter can be selected which is shown as below:
182 \arg RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports
183 \arg RCU_AFRST : reset alternate function clock
184 \arg RCU_USBFSRST: reset USBFS
185 \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6): reset TIMER
186 \arg RCU_WWDGTRST: reset WWDGT
187 \arg RCU_SPIxRST (x=0,1,2): reset SPI
188 \arg RCU_USARTxRST (x=0,1,2): reset USART
189 \arg RCU_UARTxRST (x=3,4): reset UART
190 \arg RCU_I2CxRST (x=0,1): reset I2C
191 \arg RCU_CANxRST (x=0,1): reset CAN
192 \arg RCU_PMURST: reset PMU
193 \arg RCU_DACRST: reset DAC
194 \arg RCU_ADCxRST (x=0,1): reset ADC
195 \arg RCU_BKPIRST: reset BKPI
196 \param[out] none
197 \retval none
198 */
rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)199 void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)
200 {
201 RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset));
202 }
203
204 /*!
205 \brief reset the BKP domain
206 \param[in] none
207 \param[out] none
208 \retval none
209 */
rcu_bkp_reset_enable(void)210 void rcu_bkp_reset_enable(void)
211 {
212 RCU_BDCTL |= RCU_BDCTL_BKPRST;
213 }
214
215 /*!
216 \brief disable the BKP domain reset
217 \param[in] none
218 \param[out] none
219 \retval none
220 */
rcu_bkp_reset_disable(void)221 void rcu_bkp_reset_disable(void)
222 {
223 RCU_BDCTL &= ~RCU_BDCTL_BKPRST;
224 }
225
226 /*!
227 \brief configure the system clock source
228 \param[in] ck_sys: system clock source select
229 only one parameter can be selected which is shown as below:
230 \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source
231 \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
232 \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source
233 \param[out] none
234 \retval none
235 */
rcu_system_clock_source_config(uint32_t ck_sys)236 void rcu_system_clock_source_config(uint32_t ck_sys)
237 {
238 uint32_t reg;
239
240 reg = RCU_CFG0;
241 /* reset the SCS bits and set according to ck_sys */
242 reg &= ~RCU_CFG0_SCS;
243 RCU_CFG0 = (reg | ck_sys);
244 }
245
246 /*!
247 \brief get the system clock source
248 \param[in] none
249 \param[out] none
250 \retval which clock is selected as CK_SYS source
251 \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source
252 \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source
253 \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source
254 */
rcu_system_clock_source_get(void)255 uint32_t rcu_system_clock_source_get(void)
256 {
257 return (RCU_CFG0 & RCU_CFG0_SCSS);
258 }
259
260 /*!
261 \brief configure the AHB clock prescaler selection
262 \param[in] ck_ahb: AHB clock prescaler selection
263 only one parameter can be selected which is shown as below:
264 \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
265 \param[out] none
266 \retval none
267 */
rcu_ahb_clock_config(uint32_t ck_ahb)268 void rcu_ahb_clock_config(uint32_t ck_ahb)
269 {
270 uint32_t reg;
271
272 reg = RCU_CFG0;
273
274 /* reset the AHBPSC bits and set according to ck_ahb */
275 reg &= ~RCU_CFG0_AHBPSC;
276 RCU_CFG0 = (reg | ck_ahb);
277 }
278
279 /*!
280 \brief configure the APB1 clock prescaler selection
281 \param[in] ck_apb1: APB1 clock prescaler selection
282 only one parameter can be selected which is shown as below:
283 \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
284 \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
285 \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
286 \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
287 \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
288 \param[out] none
289 \retval none
290 */
rcu_apb1_clock_config(uint32_t ck_apb1)291 void rcu_apb1_clock_config(uint32_t ck_apb1)
292 {
293 uint32_t reg;
294
295 reg = RCU_CFG0;
296
297 /* reset the APB1PSC and set according to ck_apb1 */
298 reg &= ~RCU_CFG0_APB1PSC;
299 RCU_CFG0 = (reg | ck_apb1);
300 }
301
302 /*!
303 \brief configure the APB2 clock prescaler selection
304 \param[in] ck_apb2: APB2 clock prescaler selection
305 only one parameter can be selected which is shown as below:
306 \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
307 \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
308 \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
309 \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
310 \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
311 \param[out] none
312 \retval none
313 */
rcu_apb2_clock_config(uint32_t ck_apb2)314 void rcu_apb2_clock_config(uint32_t ck_apb2)
315 {
316 uint32_t reg;
317
318 reg = RCU_CFG0;
319
320 /* reset the APB2PSC and set according to ck_apb2 */
321 reg &= ~RCU_CFG0_APB2PSC;
322 RCU_CFG0 = (reg | ck_apb2);
323 }
324
325 /*!
326 \brief configure the CK_OUT0 clock source
327 \param[in] ckout0_src: CK_OUT0 clock source selection
328 only one parameter can be selected which is shown as below:
329 \arg RCU_CKOUT0SRC_NONE: no clock selected
330 \arg RCU_CKOUT0SRC_CKSYS: system clock selected
331 \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected
332 \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected
333 \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected
334 \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected
335 \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected
336 \arg RCU_CKOUT0SRC_EXT1: EXT1 selected
337 \arg RCU_CKOUT0SRC_CKPLL2: PLL2 selected
338 \param[out] none
339 \retval none
340 */
rcu_ckout0_config(uint32_t ckout0_src)341 void rcu_ckout0_config(uint32_t ckout0_src)
342 {
343 uint32_t reg;
344
345 reg = RCU_CFG0;
346
347 /* reset the CKOUT0SRC, set according to ckout0_src */
348 reg &= ~RCU_CFG0_CKOUT0SEL;
349 RCU_CFG0 = (reg | ckout0_src);
350 }
351
352 /*!
353 \brief configure the main PLL clock
354 \param[in] pll_src: PLL clock source selection
355 only one parameter can be selected which is shown as below:
356 \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL
357 \arg RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL
358 \param[in] pll_mul: PLL clock multiplication factor
359 only one parameter can be selected which is shown as below:
360 \arg RCU_PLL_MULx (x = 2..14, 6.5, 16..32)
361 \param[out] none
362 \retval none
363 */
rcu_pll_config(uint32_t pll_src,uint32_t pll_mul)364 void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
365 {
366 uint32_t reg = 0U;
367
368 reg = RCU_CFG0;
369
370 /* PLL clock source and multiplication factor configuration */
371 reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
372 reg |= (pll_src | pll_mul);
373
374 RCU_CFG0 = reg;
375 }
376
377 /*!
378 \brief configure the PREDV0 division factor and clock source
379 \param[in] predv0_source: PREDV0 input clock source selection
380 only one parameter can be selected which is shown as below:
381 \arg RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock
382 \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock
383 \param[in] predv0_div: PREDV0 division factor
384 only one parameter can be selected which is shown as below:
385 \arg RCU_PREDV0_DIVx, x = 1..16
386 \param[out] none
387 \retval none
388 */
rcu_predv0_config(uint32_t predv0_source,uint32_t predv0_div)389 void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div)
390 {
391 uint32_t reg = 0U;
392
393 reg = RCU_CFG1;
394 /* reset PREDV0SEL and PREDV0 bits */
395 reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0);
396 /* set the PREDV0SEL and PREDV0 division factor */
397 reg |= (predv0_source | predv0_div);
398
399 RCU_CFG1 = reg;
400 }
401
402 /*!
403 \brief configure the PREDV1 division factor
404 \param[in] predv1_div: PREDV1 division factor
405 only one parameter can be selected which is shown as below:
406 \arg RCU_PREDV1_DIVx, x = 1..16
407 \param[out] none
408 \retval none
409 */
rcu_predv1_config(uint32_t predv1_div)410 void rcu_predv1_config(uint32_t predv1_div)
411 {
412 uint32_t reg = 0U;
413
414 reg = RCU_CFG1;
415 /* reset the PREDV1 bits */
416 reg &= ~RCU_CFG1_PREDV1;
417 /* set the PREDV1 division factor */
418 reg |= predv1_div;
419
420 RCU_CFG1 = reg;
421 }
422
423 /*!
424 \brief configure the PLL1 clock
425 \param[in] pll_mul: PLL clock multiplication factor
426 only one parameter can be selected which is shown as below:
427 \arg RCU_PLL1_MULx (x = 8..16, 20)
428 \param[out] none
429 \retval none
430 */
rcu_pll1_config(uint32_t pll_mul)431 void rcu_pll1_config(uint32_t pll_mul)
432 {
433 RCU_CFG1 &= ~RCU_CFG1_PLL1MF;
434 RCU_CFG1 |= pll_mul;
435 }
436
437 /*!
438 \brief configure the PLL2 clock
439 \param[in] pll_mul: PLL clock multiplication factor
440 only one parameter can be selected which is shown as below:
441 \arg RCU_PLL2_MULx (x = 8..16, 20)
442 \param[out] none
443 \retval none
444 */
rcu_pll2_config(uint32_t pll_mul)445 void rcu_pll2_config(uint32_t pll_mul)
446 {
447 RCU_CFG1 &= ~RCU_CFG1_PLL2MF;
448 RCU_CFG1 |= pll_mul;
449 }
450
451 /*!
452 \brief configure the ADC prescaler factor
453 \param[in] adc_psc: ADC prescaler factor
454 only one parameter can be selected which is shown as below:
455 \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2
456 \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4
457 \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6
458 \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8
459 \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12
460 \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16
461 \param[out] none
462 \retval none
463 */
rcu_adc_clock_config(uint32_t adc_psc)464 void rcu_adc_clock_config(uint32_t adc_psc)
465 {
466 uint32_t reg0;
467
468 /* reset the ADCPSC bits */
469 reg0 = RCU_CFG0;
470 reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC);
471
472 /* set the ADC prescaler factor */
473 switch(adc_psc){
474 case RCU_CKADC_CKAPB2_DIV2:
475 case RCU_CKADC_CKAPB2_DIV4:
476 case RCU_CKADC_CKAPB2_DIV6:
477 case RCU_CKADC_CKAPB2_DIV8:
478 reg0 |= (adc_psc << 14);
479 break;
480
481 case RCU_CKADC_CKAPB2_DIV12:
482 case RCU_CKADC_CKAPB2_DIV16:
483 adc_psc &= ~BIT(2);
484 reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2);
485 break;
486
487 default:
488 break;
489 }
490
491 /* set the register */
492 RCU_CFG0 = reg0;
493 }
494
495 /*!
496 \brief configure the USBFS prescaler factor
497 \param[in] usb_psc: USB prescaler factor
498 only one parameter can be selected which is shown as below:
499 \arg RCU_CKUSB_CKPLL_DIV1_5: USBFS prescaler select CK_PLL/1.5
500 \arg RCU_CKUSB_CKPLL_DIV1: USBFS prescaler select CK_PLL/1
501 \arg RCU_CKUSB_CKPLL_DIV2_5: USBFS prescaler select CK_PLL/2.5
502 \arg RCU_CKUSB_CKPLL_DIV2: USBFS prescaler select CK_PLL/2
503 \param[out] none
504 \retval none
505 */
rcu_usb_clock_config(uint32_t usb_psc)506 void rcu_usb_clock_config(uint32_t usb_psc)
507 {
508 uint32_t reg;
509
510 reg = RCU_CFG0;
511
512 /* configure the USBFS prescaler factor */
513 reg &= ~RCU_CFG0_USBFSPSC;
514 RCU_CFG0 = (reg | usb_psc);
515 }
516
517 /*!
518 \brief configure the RTC clock source selection
519 \param[in] rtc_clock_source: RTC clock source selection
520 only one parameter can be selected which is shown as below:
521 \arg RCU_RTCSRC_NONE: no clock selected
522 \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
523 \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock
524 \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock
525 \param[out] none
526 \retval none
527 */
rcu_rtc_clock_config(uint32_t rtc_clock_source)528 void rcu_rtc_clock_config(uint32_t rtc_clock_source)
529 {
530 uint32_t reg;
531
532 reg = RCU_BDCTL;
533 /* reset the RTCSRC bits and set according to rtc_clock_source */
534 reg &= ~RCU_BDCTL_RTCSRC;
535 RCU_BDCTL = (reg | rtc_clock_source);
536 }
537
538 /*!
539 \brief configure the I2S1 clock source selection
540 \param[in] i2s_clock_source: I2S1 clock source selection
541 only one parameter can be selected which is shown as below:
542 \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock
543 \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock
544 \param[out] none
545 \retval none
546 */
rcu_i2s1_clock_config(uint32_t i2s_clock_source)547 void rcu_i2s1_clock_config(uint32_t i2s_clock_source)
548 {
549 uint32_t reg;
550
551 reg = RCU_CFG1;
552 /* reset the I2S1SEL bit and set according to i2s_clock_source */
553 reg &= ~RCU_CFG1_I2S1SEL;
554 RCU_CFG1 = (reg | i2s_clock_source);
555 }
556
557 /*!
558 \brief configure the I2S2 clock source selection
559 \param[in] i2s_clock_source: I2S2 clock source selection
560 only one parameter can be selected which is shown as below:
561 \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock
562 \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock
563 \param[out] none
564 \retval none
565 */
rcu_i2s2_clock_config(uint32_t i2s_clock_source)566 void rcu_i2s2_clock_config(uint32_t i2s_clock_source)
567 {
568 uint32_t reg;
569
570 reg = RCU_CFG1;
571 /* reset the I2S2SEL bit and set according to i2s_clock_source */
572 reg &= ~RCU_CFG1_I2S2SEL;
573 RCU_CFG1 = (reg | i2s_clock_source);
574 }
575
576 /*!
577 \brief get the clock stabilization and periphral reset flags
578 \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
579 only one parameter can be selected which is shown as below:
580 \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag
581 \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag
582 \arg RCU_FLAG_PLLSTB: PLL stabilization flag
583 \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag
584 \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag
585 \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag
586 \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag
587 \arg RCU_FLAG_EPRST: external PIN reset flag
588 \arg RCU_FLAG_PORRST: power reset flag
589 \arg RCU_FLAG_SWRST: software reset flag
590 \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag
591 \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag
592 \arg RCU_FLAG_LPRST: low-power reset flag
593 \param[out] none
594 \retval FlagStatus: SET or RESET
595 */
rcu_flag_get(rcu_flag_enum flag)596 FlagStatus rcu_flag_get(rcu_flag_enum flag)
597 {
598 /* get the rcu flag */
599 if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
600 return SET;
601 }else{
602 return RESET;
603 }
604 }
605
606 /*!
607 \brief clear all the reset flag
608 \param[in] none
609 \param[out] none
610 \retval none
611 */
rcu_all_reset_flag_clear(void)612 void rcu_all_reset_flag_clear(void)
613 {
614 RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
615 }
616
617 /*!
618 \brief get the clock stabilization interrupt and ckm flags
619 \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
620 only one parameter can be selected which is shown as below:
621 \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag
622 \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
623 \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag
624 \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
625 \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
626 \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag
627 \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag
628 \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
629 \param[out] none
630 \retval FlagStatus: SET or RESET
631 */
rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)632 FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
633 {
634 /* get the rcu interrupt flag */
635 if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
636 return SET;
637 }else{
638 return RESET;
639 }
640 }
641
642 /*!
643 \brief clear the interrupt flags
644 \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
645 only one parameter can be selected which is shown as below:
646 \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear
647 \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
648 \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear
649 \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
650 \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
651 \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear
652 \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear
653 \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
654 \param[out] none
655 \retval none
656 */
rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)657 void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
658 {
659 RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
660 }
661
662 /*!
663 \brief enable the stabilization interrupt
664 \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
665 Only one parameter can be selected which is shown as below:
666 \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
667 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
668 \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
669 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
670 \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
671 \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable
672 \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable
673 \param[out] none
674 \retval none
675 */
rcu_interrupt_enable(rcu_int_enum stab_int)676 void rcu_interrupt_enable(rcu_int_enum stab_int)
677 {
678 RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
679 }
680
681 /*!
682 \brief disable the stabilization interrupt
683 \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
684 only one parameter can be selected which is shown as below:
685 \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
686 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
687 \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
688 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
689 \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
690 \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable
691 \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable
692 \param[out] none
693 \retval none
694 */
rcu_interrupt_disable(rcu_int_enum stab_int)695 void rcu_interrupt_disable(rcu_int_enum stab_int)
696 {
697 RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
698 }
699
700 /*!
701 \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout
702 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
703 only one parameter can be selected which is shown as below:
704 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
705 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
706 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
707 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
708 \arg RCU_PLL_CK: phase locked loop(PLL)
709 \arg RCU_PLL1_CK: phase locked loop 1
710 \arg RCU_PLL2_CK: phase locked loop 2
711 \param[out] none
712 \retval ErrStatus: SUCCESS or ERROR
713 */
rcu_osci_stab_wait(rcu_osci_type_enum osci)714 ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
715 {
716 uint32_t stb_cnt = 0U;
717 ErrStatus reval = ERROR;
718 FlagStatus osci_stat = RESET;
719
720 switch(osci){
721 /* wait HXTAL stable */
722 case RCU_HXTAL:
723 while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){
724 osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
725 stb_cnt++;
726 }
727
728 /* check whether flag is set or not */
729 if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){
730 reval = SUCCESS;
731 }
732 break;
733
734 /* wait LXTAL stable */
735 case RCU_LXTAL:
736 while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){
737 osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
738 stb_cnt++;
739 }
740
741 /* check whether flag is set or not */
742 if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){
743 reval = SUCCESS;
744 }
745 break;
746
747 /* wait IRC8M stable */
748 case RCU_IRC8M:
749 while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){
750 osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB);
751 stb_cnt++;
752 }
753
754 /* check whether flag is set or not */
755 if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){
756 reval = SUCCESS;
757 }
758 break;
759
760 /* wait IRC40K stable */
761 case RCU_IRC40K:
762 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
763 osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB);
764 stb_cnt++;
765 }
766
767 /* check whether flag is set or not */
768 if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){
769 reval = SUCCESS;
770 }
771 break;
772
773 /* wait PLL stable */
774 case RCU_PLL_CK:
775 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
776 osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
777 stb_cnt++;
778 }
779
780 /* check whether flag is set or not */
781 if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){
782 reval = SUCCESS;
783 }
784 break;
785 /* wait PLL1 stable */
786 case RCU_PLL1_CK:
787 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
788 osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB);
789 stb_cnt++;
790 }
791
792 /* check whether flag is set or not */
793 if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){
794 reval = SUCCESS;
795 }
796 break;
797 /* wait PLL2 stable */
798 case RCU_PLL2_CK:
799 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
800 osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB);
801 stb_cnt++;
802 }
803
804 /* check whether flag is set or not */
805 if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){
806 reval = SUCCESS;
807 }
808 break;
809
810 default:
811 break;
812 }
813
814 /* return value */
815 return reval;
816 }
817
818 /*!
819 \brief turn on the oscillator
820 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
821 only one parameter can be selected which is shown as below:
822 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
823 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
824 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
825 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
826 \arg RCU_PLL_CK: phase locked loop(PLL)
827 \arg RCU_PLL1_CK: phase locked loop 1
828 \arg RCU_PLL2_CK: phase locked loop 2
829 \param[out] none
830 \retval none
831 */
rcu_osci_on(rcu_osci_type_enum osci)832 void rcu_osci_on(rcu_osci_type_enum osci)
833 {
834 RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
835 }
836
837 /*!
838 \brief turn off the oscillator
839 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
840 only one parameter can be selected which is shown as below:
841 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
842 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
843 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
844 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
845 \arg RCU_PLL_CK: phase locked loop(PLL)
846 \arg RCU_PLL1_CK: phase locked loop 1
847 \arg RCU_PLL2_CK: phase locked loop 2
848 \param[out] none
849 \retval none
850 */
rcu_osci_off(rcu_osci_type_enum osci)851 void rcu_osci_off(rcu_osci_type_enum osci)
852 {
853 RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
854 }
855
856 /*!
857 \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
858 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
859 only one parameter can be selected which is shown as below:
860 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
861 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
862 \param[out] none
863 \retval none
864 */
rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)865 void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
866 {
867 uint32_t reg;
868
869 switch(osci){
870 /* enable HXTAL to bypass mode */
871 case RCU_HXTAL:
872 reg = RCU_CTL;
873 RCU_CTL &= ~RCU_CTL_HXTALEN;
874 RCU_CTL = (reg | RCU_CTL_HXTALBPS);
875 break;
876 /* enable LXTAL to bypass mode */
877 case RCU_LXTAL:
878 reg = RCU_BDCTL;
879 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
880 RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
881 break;
882 case RCU_IRC8M:
883 case RCU_IRC40K:
884 case RCU_PLL_CK:
885 case RCU_PLL1_CK:
886 case RCU_PLL2_CK:
887 break;
888 default:
889 break;
890 }
891 }
892
893 /*!
894 \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
895 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
896 only one parameter can be selected which is shown as below:
897 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
898 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
899 \param[out] none
900 \retval none
901 */
rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)902 void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
903 {
904 uint32_t reg;
905
906 switch(osci){
907 /* disable HXTAL to bypass mode */
908 case RCU_HXTAL:
909 reg = RCU_CTL;
910 RCU_CTL &= ~RCU_CTL_HXTALEN;
911 RCU_CTL = (reg & ~RCU_CTL_HXTALBPS);
912 break;
913 /* disable LXTAL to bypass mode */
914 case RCU_LXTAL:
915 reg = RCU_BDCTL;
916 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
917 RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS);
918 break;
919 case RCU_IRC8M:
920 case RCU_IRC40K:
921 case RCU_PLL_CK:
922 case RCU_PLL1_CK:
923 case RCU_PLL2_CK:
924 break;
925 default:
926 break;
927 }
928 }
929
930 /*!
931 \brief enable the HXTAL clock monitor
932 \param[in] none
933 \param[out] none
934 \retval none
935 */
936
rcu_hxtal_clock_monitor_enable(void)937 void rcu_hxtal_clock_monitor_enable(void)
938 {
939 RCU_CTL |= RCU_CTL_CKMEN;
940 }
941
942 /*!
943 \brief disable the HXTAL clock monitor
944 \param[in] none
945 \param[out] none
946 \retval none
947 */
rcu_hxtal_clock_monitor_disable(void)948 void rcu_hxtal_clock_monitor_disable(void)
949 {
950 RCU_CTL &= ~RCU_CTL_CKMEN;
951 }
952
953 /*!
954 \brief set the IRC8M adjust value
955 \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F
956 \param[out] none
957 \retval none
958 */
rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)959 void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)
960 {
961 uint32_t reg;
962
963 reg = RCU_CTL;
964 /* reset the IRC8MADJ bits and set according to irc8m_adjval */
965 reg &= ~RCU_CTL_IRC8MADJ;
966 RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3));
967 }
968
969 /*!
970 \brief deep-sleep mode voltage select
971 \param[in] dsvol: deep sleep mode voltage
972 only one parameter can be selected which is shown as below:
973 \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V
974 \arg RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V
975 \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V
976 \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V
977 \param[out] none
978 \retval none
979 */
rcu_deepsleep_voltage_set(uint32_t dsvol)980 void rcu_deepsleep_voltage_set(uint32_t dsvol)
981 {
982 dsvol &= RCU_DSV_DSLPVS;
983 RCU_DSV = dsvol;
984 }
985
986 /*!
987 \brief get the system clock, bus and peripheral clock frequency
988 \param[in] clock: the clock frequency which to get
989 only one parameter can be selected which is shown as below:
990 \arg CK_SYS: system clock frequency
991 \arg CK_AHB: AHB clock frequency
992 \arg CK_APB1: APB1 clock frequency
993 \arg CK_APB2: APB2 clock frequency
994 \param[out] none
995 \retval clock frequency of system, AHB, APB1, APB2
996 */
rcu_clock_freq_get(rcu_clock_freq_enum clock)997 uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
998 {
999 uint32_t sws, ck_freq = 0U;
1000 uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq;
1001 uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp;
1002 uint32_t predv0, predv1, pll1mf;
1003
1004 /* exponent of AHB, APB1 and APB2 clock divider */
1005 uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
1006 uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1007 uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1008
1009 sws = GET_BITS(RCU_CFG0, 2, 3);
1010 switch(sws){
1011 /* IRC8M is selected as CK_SYS */
1012 case SEL_IRC8M:
1013 cksys_freq = IRC8M_VALUE;
1014 break;
1015 /* HXTAL is selected as CK_SYS */
1016 case SEL_HXTAL:
1017 cksys_freq = HXTAL_VALUE;
1018 break;
1019 /* PLL is selected as CK_SYS */
1020 case SEL_PLL:
1021 /* PLL clock source selection, HXTAL or IRC8M/2 */
1022 pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
1023
1024 if(RCU_PLLSRC_HXTAL == pllsel) {
1025 /* PLL clock source is HXTAL */
1026 ck_src = HXTAL_VALUE;
1027
1028 predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
1029 /* source clock use PLL1 */
1030 if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
1031 predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
1032 pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
1033 if(17U == pll1mf){
1034 pll1mf = 20U;
1035 }
1036 ck_src = (ck_src / predv1) * pll1mf;
1037 }
1038 predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
1039 ck_src /= predv0;
1040 }else{
1041 /* PLL clock source is IRC8M/2 */
1042 ck_src = IRC8M_VALUE/2U;
1043 }
1044
1045 /* PLL multiplication factor */
1046 pllmf = GET_BITS(RCU_CFG0, 18, 21);
1047 if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
1048 pllmf |= 0x10U;
1049 }
1050 if(pllmf < 15U){
1051 pllmf += 2U;
1052 }else{
1053 pllmf += 1U;
1054 }
1055
1056 cksys_freq = ck_src * pllmf;
1057
1058 if(15U == pllmf){
1059 /* PLL source clock multiply by 6.5 */
1060 cksys_freq = ck_src * 6U + ck_src / 2U;
1061 }
1062
1063 break;
1064 /* IRC8M is selected as CK_SYS */
1065 default:
1066 cksys_freq = IRC8M_VALUE;
1067 break;
1068 }
1069
1070 /* calculate AHB clock frequency */
1071 idx = GET_BITS(RCU_CFG0, 4, 7);
1072 clk_exp = ahb_exp[idx];
1073 ahb_freq = cksys_freq >> clk_exp;
1074
1075 /* calculate APB1 clock frequency */
1076 idx = GET_BITS(RCU_CFG0, 8, 10);
1077 clk_exp = apb1_exp[idx];
1078 apb1_freq = ahb_freq >> clk_exp;
1079
1080 /* calculate APB2 clock frequency */
1081 idx = GET_BITS(RCU_CFG0, 11, 13);
1082 clk_exp = apb2_exp[idx];
1083 apb2_freq = ahb_freq >> clk_exp;
1084
1085 /* return the clocks frequency */
1086 switch(clock){
1087 case CK_SYS:
1088 ck_freq = cksys_freq;
1089 break;
1090 case CK_AHB:
1091 ck_freq = ahb_freq;
1092 break;
1093 case CK_APB1:
1094 ck_freq = apb1_freq;
1095 break;
1096 case CK_APB2:
1097 ck_freq = apb2_freq;
1098 break;
1099 default:
1100 break;
1101 }
1102 return ck_freq;
1103 }
1104