1313#include <gd32e10x_rcu.h>
1414#include <gd32e10x.h>
1515
16+ #define DT_FREQ_M (x ) ((x) * 1000 * 1000) // todo: use dts/common/freq.h
1617
1718#define RCC_BASE DT_REG_ADDR_BY_IDX(DT_NODELABEL(rcc), 0)
1819#undef RCU_REG_VAL
1920#define RCU_REG_VAL (periph ) (REG32(RCC_BASE | periph ))
2021
22+ #define DT_CLOCK_SRC (clk ) DT_PHANDLE_BY_IDX(DT_NODELABEL(clk), clocks, 0)
23+
2124static inline int gd32_clock_reset ()
2225{
2326 /* reset the RCU clock configuration to the default reset state */
@@ -39,76 +42,129 @@ static inline int gd32_clock_reset()
3942 return 0 ;
4043}
4144
42- static inline void system_clock_120m_hxtal (void )
45+ static inline void clock_enable_hsi (void )
4346{
44- uint32_t timeout = 0U ;
45- uint32_t stab_flag = 0U ;
46-
47- /* enable HXTAL */
48- RCU_CTL |= RCU_CTL_HXTALEN ;
49-
50- /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
51- do {
52- timeout ++ ;
53- stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB );
54- }while ((0U == stab_flag ) && (HXTAL_STARTUP_TIMEOUT != timeout ));
55-
56- /* if fail */
57- if (0U == (RCU_CTL & RCU_CTL_HXTALSTB )){
58- while (1 ){
59- }
60- }
61-
62- FMC_WS = (FMC_WS & (~FMC_WS_WSCNT )) | FMC_WAIT_STATE_3 ;
63-
64- /* HXTAL is stable */
65- /* AHB = SYSCLK */
66- RCU_CFG0 |= RCU_AHB_CKSYS_DIV1 ;
67- /* APB2 = AHB/1 */
68- RCU_CFG0 |= RCU_APB2_CKAHB_DIV1 ;
69- /* APB1 = AHB/2 */
70- RCU_CFG0 |= RCU_APB1_CKAHB_DIV2 ;
71-
72- /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */
73- RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 );
74- RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30 );
75-
76- RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0 );
77- #ifdef HXTAL_VALUE_8M
78- /* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
79- RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10 );
80- #elif defined (HXTAL_VALUE_25M )
81- /* CK_PREDIV0 = (CK_HXTAL)/5 *8/10 = 4 MHz */
82- RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10 );
83- #endif
84-
85- /* enable PLL1 */
86- RCU_CTL |= RCU_CTL_PLL1EN ;
87- /* wait till PLL1 is ready */
88- while ((RCU_CTL & RCU_CTL_PLL1STB ) == 0U ){
89- }
90-
91- /* enable PLL */
92- RCU_CTL |= RCU_CTL_PLLEN ;
93-
94- /* wait until PLL is stable */
95- while (0U == (RCU_CTL & RCU_CTL_PLLSTB )){
96- }
97-
98- /* select PLL as system clock */
99- RCU_CFG0 &= ~RCU_CFG0_SCS ;
100- RCU_CFG0 |= RCU_CKSYSSRC_PLL ;
101-
102- /* wait until PLL is selected as system clock */
103- while (0U == (RCU_CFG0 & RCU_SCSS_PLL )){
104- }
47+ uint32_t timeout = 0U ;
48+ uint32_t stab_flag = 0U ;
49+
50+ /* enable IRC8M */
51+ RCU_CTL |= RCU_CTL_IRC8MEN ;
52+
53+ /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
54+ do {
55+ timeout ++ ;
56+ stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB );
57+ }while ((0U == stab_flag ) && (IRC8M_STARTUP_TIMEOUT != timeout ));
58+
59+ /* if fail */
60+ if (0U == (RCU_CTL & RCU_CTL_IRC8MSTB )){
61+ while (1 ){
62+ }
63+ }
10564}
10665
107- static inline int gd32_clock_init ( )
66+ static inline void clock_enable_hse ( void )
10867{
109- system_clock_120m_hxtal ();
68+ uint32_t timeout = 0U ;
69+ uint32_t stab_flag = 0U ;
70+ /* enable HXTAL */
71+ RCU_CTL |= RCU_CTL_HXTALEN ;
72+
73+ /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
74+ do {
75+ timeout ++ ;
76+ stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB );
77+ }while ((0U == stab_flag ) && (HXTAL_STARTUP_TIMEOUT != timeout ));
78+
79+ /* if fail */
80+ if (0U == (RCU_CTL & RCU_CTL_HXTALSTB )){
81+ while (1 ){
82+ }
83+ }
84+ }
11085
111- return 0 ;
86+ static inline void clock_flash_config (void )
87+ {
88+ #if DT_PROP (DT_NODELABEL (rcc ), clock_frequency ) <= DT_FREQ_M (30 )
89+ FMC_WS = (FMC_WS & (~FMC_WS_WSCNT )) | FMC_WAIT_STATE_0 ;
90+ #elif DT_PROP (DT_NODELABEL (rcc ), clock_frequency ) <= DT_FREQ_M (60 )
91+ FMC_WS = (FMC_WS & (~FMC_WS_WSCNT )) | FMC_WAIT_STATE_1 ;
92+ #elif DT_PROP (DT_NODELABEL (rcc ), clock_frequency ) <= DT_FREQ_M (90 )
93+ FMC_WS = (FMC_WS & (~FMC_WS_WSCNT )) | FMC_WAIT_STATE_2 ;
94+ #elif DT_PROP (DT_NODELABEL (rcc ), clock_frequency ) <= DT_FREQ_M (120 )
95+ FMC_WS = (FMC_WS & (~FMC_WS_WSCNT )) | FMC_WAIT_STATE_3 ;
96+ #else
97+ #error "GD32 RCC Freq too High"
98+ #endif // clock freq select
99+ }
100+
101+ static inline void clock_peripherals_config (void )
102+ {
103+ // set ahb,apb1,apb2
104+ RCU_CFG0 |= UTIL_CAT (RCU_AHB_CKSYS_DIV , DT_PROP (DT_NODELABEL (rcc ), ahb_prescaler ));
105+ RCU_CFG0 |= UTIL_CAT (RCU_APB1_CKAHB_DIV , DT_PROP (DT_NODELABEL (rcc ), apb1_prescaler ));
106+ RCU_CFG0 |= UTIL_CAT (RCU_APB2_CKAHB_DIV , DT_PROP (DT_NODELABEL (rcc ), apb2_prescaler ));
107+ }
108+
109+ // only 120M with hsi/hse is tested.
110+ static inline void clock_pll_config (void )
111+ {
112+ // set pll src
113+ #if DT_NODE_HAS_COMPAT (DT_CLOCK_SRC (pll ), gd_gd32_hse_clock ) // hse clk
114+ RCU_CFG0 |= RCU_PLLSRC_HXTAL_IRC48M ;
115+ #elif DT_NODE_HAS_COMPAT (DT_CLOCK_SRC (pll ), fixed_clock ) // hsi enable
116+ #else
117+ #error "pll src not support."
118+ #endif // DT_NODELABEL(clk_hse) == DT_PHANDLE_BY_IDX(DT_NODELABEL(pll), clocks, 0)
119+
120+ // set pll MUL
121+ RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 );
122+ RCU_CFG0 |= UTIL_CAT (RCU_PLL_MUL , DT_PROP (DT_NODELABEL (pll ), mul ));
123+
124+ #if DT_NODE_HAS_COMPAT (DT_CLOCK_SRC (rcc ), gd_gd32e103_pll_clock )
125+
126+ #if DT_NODE_HAS_COMPAT (DT_CLOCK_SRC (pll ), gd_gd32_hse_clock ) // hse clk
127+ RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0 );
128+ RCU_CFG1 |= RCU_PLLPRESRC_HXTAL ;
129+ RCU_CFG1 |= RCU_PREDV0SRC_CKPLL1 ;
130+ RCU_CFG1 |= RCU_PLL1_MUL10 ;
131+ RCU_CFG1 |= RCU_PREDV1_DIV2 ;
132+ RCU_CFG1 |= RCU_PREDV0_DIV10 ;
133+ #elif DT_NODE_HAS_COMPAT (DT_CLOCK_SRC (pll ), fixed_clock ) // hsi enable
134+ // not need config
135+ #else // not hse/hsi
136+ #error "clock src not support yet."
137+ #endif // hse/hsi switch
138+
139+ #else //DT_NODE_HAS_COMPAT(DT_CLOCK_SRC(rcc), gd_gd32e103_pll_clock)
140+ #error "config rcc not with pll is support yet."
141+ #endif //DT_NODE_HAS_COMPAT(DT_CLOCK_SRC(rcc), gd_gd32e103_pll_clock)
142+
143+ #if DT_NODE_HAS_COMPAT (DT_CLOCK_SRC (pll ), gd_gd32_hse_clock ) // hse clk
144+ /* enable PLL1 */
145+ RCU_CTL |= RCU_CTL_PLL1EN ;
146+ /* wait till PLL1 is ready */
147+ while ((RCU_CTL & RCU_CTL_PLL1STB ) == 0U ){
148+ }
149+ #endif // hse clk only
150+
151+ /* enable PLL */
152+ RCU_CTL |= RCU_CTL_PLLEN ;
153+
154+ /* wait until PLL is stable */
155+ while (0U == (RCU_CTL & RCU_CTL_PLLSTB )){
156+ }
157+ }
158+
159+ static inline void clock_pll_select (void )
160+ {
161+ /* select PLL as system clock */
162+ RCU_CFG0 &= ~RCU_CFG0_SCS ;
163+ RCU_CFG0 |= RCU_CKSYSSRC_PLL ;
164+
165+ /* wait until PLL is selected as system clock */
166+ while (0U == (RCU_CFG0 & RCU_SCSS_PLL )){
167+ }
112168}
113169
114170/**
@@ -125,8 +181,27 @@ static inline int gd32_clock_init()
125181 */
126182int gd32_clock_control_init (const struct device * dev )
127183{
184+ ARG_UNUSED (dev );
185+
128186 gd32_clock_reset ();
129- gd32_clock_init ();
187+
188+ #if DT_HAS_COMPAT_STATUS_OKAY (gd_gd32_hse_clock )
189+ clock_enable_hse ();
190+ #else
191+ clock_enable_hsi ();
192+ #endif // DT_HAS_COMPAT_STATUS_OKAY(gd_gd32_hse_clock)
193+
194+ clock_flash_config ();
195+
196+ clock_peripherals_config ();
197+
198+ #if DT_HAS_COMPAT_STATUS_OKAY (gd_gd32e103_pll_clock )
199+ clock_pll_config ();
200+
201+ #if DT_NODE_HAS_COMPAT (DT_CLOCK_SRC (rcc ), gd_gd32e103_pll_clock )
202+ clock_pll_select ();
203+ #endif //DT_NODE_HAS_COMPAT(DT_CLOCK_SRC(rcc), gd_gd32e103_pll_clock)
204+ #endif // DT_HAS_COMPAT_STATUS_OKAY(gd_gd32e103_pll_clock)
130205
131206 return 0 ;
132207}
@@ -139,6 +214,10 @@ static inline int gd32_clock_control_on(const struct device *dev,
139214
140215 switch (pclken -> bus )
141216 {
217+ case GD32_CLOCK_BUS_AHB1 :
218+ RCU_REG_VAL (AHBEN_REG_OFFSET ) |= pclken -> enr ;
219+ break ;
220+
142221 case GD32_CLOCK_BUS_APB1 :
143222 RCU_REG_VAL (APB1EN_REG_OFFSET ) |= pclken -> enr ;
144223 break ;
@@ -148,6 +227,7 @@ static inline int gd32_clock_control_on(const struct device *dev,
148227 break ;
149228
150229 default :
230+ __ASSERT_NO_MSG (0 );
151231 break ;
152232 }
153233
@@ -157,13 +237,15 @@ static inline int gd32_clock_control_on(const struct device *dev,
157237static inline int gd32_clock_control_off (const struct device * dev ,
158238 clock_control_subsys_t sub_system )
159239{
240+ //todo: work later
160241 return 0 ;
161242}
162243
163244static int gd32_clock_control_get_subsys_rate (const struct device * clock ,
164245 clock_control_subsys_t sub_system ,
165246 uint32_t * rate )
166247{
248+ //todo: work later
167249 return 0 ;
168250}
169251
@@ -184,3 +266,6 @@ DEVICE_DT_DEFINE(DT_NODELABEL(rcc),
184266 PRE_KERNEL_1 ,
185267 CONFIG_CLOCK_CONTROL_GD32_DEVICE_INIT_PRIORITY ,
186268 & gd32_clock_control_api );
269+
270+ BUILD_ASSERT (DT_PROP (DT_NODELABEL (rcc ), clock_frequency )== CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC ,
271+ "CPU Freq not same in `kconfig->CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC` & `devicetree->rcc->clock-frequency`" );
0 commit comments