Skip to content

Commit b1a41a6

Browse files
committed
driver: gd32_rcu: Add RCU Driver.
Add RCU Driver. Signed-off-by: YuLong Yao <[email protected]>
1 parent 941dd61 commit b1a41a6

File tree

4 files changed

+159
-69
lines changed

4 files changed

+159
-69
lines changed

boards/arm/gd32e103v_eval/gd32e103v_eval.dts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,14 @@
5050
};
5151
};
5252

53+
&clk_hse {
54+
status = "okay";
55+
clock-frequency = <DT_FREQ_M(8)>;
56+
};
57+
5358
&pll {
5459
status = "okay";
55-
clocks = <&clk_hsi>;
60+
clocks = <&clk_hse>;
5661
prediv = <2>;
5762
mul = <27>;
5863
};

boards/arm/gd32e103v_eval/gd32e103v_eval_defconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
CONFIG_SOC_SERIES_GD32E1X=y
44
CONFIG_SOC_GD32E103VB=y
5-
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000
5+
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=108000000
66

77
# Enable MPU
88
# CONFIG_ARM_MPU=y

drivers/clock_control/clock_gd32e1.c

Lines changed: 151 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@
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+
2124
static 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
*/
126182
int 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,
157237
static 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

163244
static 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`");

dts/arm/gigadevice/e1/gd32e1.dtsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
clocks {
3737
clk_hse: clk-hse {
3838
#clock-cells = <0>;
39-
compatible = "st,stm32-hse-clock";
39+
compatible = "gd,gd32-hse-clock";
4040
status = "disabled";
4141
};
4242

0 commit comments

Comments
 (0)