Skip to content

Commit 4dd3ae9

Browse files
HaiLong Yangcameled
authored andcommitted
drivers: serial: gd32 usart add interrupt support
Add interrupt support for gd32 usart driver. Signed-off-by: HaiLong Yang <[email protected]>
1 parent db8ddef commit 4dd3ae9

File tree

5 files changed

+292
-13
lines changed

5 files changed

+292
-13
lines changed

drivers/serial/Kconfig.gd32

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ config USART_GD32
99
default $(dt_compat_enabled,$(DT_COMPAT_GIGADEVICE_GD32_USART))
1010
depends on SOC_FAMILY_GD32
1111
select SERIAL_HAS_DRIVER
12+
select SERIAL_SUPPORT_INTERRUPT
1213
select USE_GD32_USART
1314
help
1415
This option enables the USART driver for GD32 SoC family.

drivers/serial/usart_gd32.c

Lines changed: 178 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,30 @@ struct gd32_usart_config {
1414
uint32_t rcu_periph_clock;
1515
const struct pinctrl_dev_config *pcfg;
1616
uint32_t parity;
17+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
18+
uart_irq_config_func_t irq_config_func;
19+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
1720
};
1821

1922
struct gd32_usart_data {
2023
uint32_t baud_rate;
24+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
25+
uart_irq_callback_user_data_t user_cb;
26+
void *user_data;
27+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
2128
};
2229

30+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
31+
static void usart_gd32_isr(const struct device *dev)
32+
{
33+
struct gd32_usart_data *const data = dev->data;
34+
35+
if (data->user_cb) {
36+
data->user_cb(dev, data->user_data);
37+
}
38+
}
39+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
40+
2341
static int usart_gd32_init(const struct device *dev)
2442
{
2543
const struct gd32_usart_config *const cfg = dev->config;
@@ -65,6 +83,10 @@ static int usart_gd32_init(const struct device *dev)
6583
usart_transmit_config(cfg->reg, USART_TRANSMIT_ENABLE);
6684
usart_enable(cfg->reg);
6785

86+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
87+
cfg->irq_config_func(dev);
88+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
89+
6890
return 0;
6991
}
7092

@@ -124,29 +146,180 @@ static int usart_gd32_err_check(const struct device *dev)
124146
return errors;
125147
}
126148

149+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
150+
int usart_gd32_fifo_fill(const struct device *dev, const uint8_t *tx_data,
151+
int len)
152+
{
153+
const struct gd32_usart_config *const cfg = dev->config;
154+
uint8_t num_tx = 0U;
155+
156+
while ((len - num_tx > 0) &&
157+
usart_flag_get(cfg->reg, USART_FLAG_TBE)) {
158+
usart_data_transmit(cfg->reg, tx_data[num_tx++]);
159+
}
160+
161+
return num_tx;
162+
}
163+
164+
int usart_gd32_fifo_read(const struct device *dev, uint8_t *rx_data,
165+
const int size)
166+
{
167+
const struct gd32_usart_config *const cfg = dev->config;
168+
uint8_t num_rx = 0U;
169+
170+
while ((size - num_rx > 0) &&
171+
usart_flag_get(cfg->reg, USART_FLAG_RBNE)) {
172+
rx_data[num_rx++] = usart_data_receive(cfg->reg);
173+
}
174+
175+
return num_rx;
176+
}
177+
178+
void usart_gd32_irq_tx_enable(const struct device *dev)
179+
{
180+
const struct gd32_usart_config *const cfg = dev->config;
181+
182+
usart_interrupt_enable(cfg->reg, USART_INT_TC);
183+
}
184+
185+
void usart_gd32_irq_tx_disable(const struct device *dev)
186+
{
187+
const struct gd32_usart_config *const cfg = dev->config;
188+
189+
usart_interrupt_disable(cfg->reg, USART_INT_TC);
190+
}
191+
192+
int usart_gd32_irq_tx_ready(const struct device *dev)
193+
{
194+
const struct gd32_usart_config *const cfg = dev->config;
195+
196+
return usart_flag_get(cfg->reg, USART_FLAG_TBE) &&
197+
usart_interrupt_flag_get(cfg->reg, USART_INT_FLAG_TC);
198+
}
199+
200+
int usart_gd32_irq_tx_complete(const struct device *dev)
201+
{
202+
const struct gd32_usart_config *const cfg = dev->config;
203+
204+
return usart_flag_get(cfg->reg, USART_FLAG_TC);
205+
}
206+
207+
void usart_gd32_irq_rx_enable(const struct device *dev)
208+
{
209+
const struct gd32_usart_config *const cfg = dev->config;
210+
211+
usart_interrupt_enable(cfg->reg, USART_INT_RBNE);
212+
}
213+
214+
void usart_gd32_irq_rx_disable(const struct device *dev)
215+
{
216+
const struct gd32_usart_config *const cfg = dev->config;
217+
218+
usart_interrupt_disable(cfg->reg, USART_INT_RBNE);
219+
}
220+
221+
int usart_gd32_irq_rx_ready(const struct device *dev)
222+
{
223+
const struct gd32_usart_config *const cfg = dev->config;
224+
225+
return usart_flag_get(cfg->reg, USART_FLAG_RBNE);
226+
}
227+
228+
void usart_gd32_irq_err_enable(const struct device *dev)
229+
{
230+
const struct gd32_usart_config *const cfg = dev->config;
231+
232+
usart_interrupt_enable(cfg->reg, USART_INT_ERR);
233+
usart_interrupt_enable(cfg->reg, USART_INT_PERR);
234+
}
235+
236+
void usart_gd32_irq_err_disable(const struct device *dev)
237+
{
238+
const struct gd32_usart_config *const cfg = dev->config;
239+
240+
usart_interrupt_disable(cfg->reg, USART_INT_ERR);
241+
usart_interrupt_disable(cfg->reg, USART_INT_PERR);
242+
}
243+
244+
int usart_gd32_irq_is_pending(const struct device *dev)
245+
{
246+
const struct gd32_usart_config *const cfg = dev->config;
247+
248+
return ((usart_flag_get(cfg->reg, USART_FLAG_RBNE) &&
249+
usart_interrupt_flag_get(cfg->reg, USART_INT_FLAG_RBNE)) ||
250+
(usart_flag_get(cfg->reg, USART_FLAG_TC) &&
251+
usart_interrupt_flag_get(cfg->reg, USART_INT_FLAG_TC)));
252+
}
253+
254+
void usart_gd32_irq_callback_set(const struct device *dev,
255+
uart_irq_callback_user_data_t cb,
256+
void *user_data)
257+
{
258+
struct gd32_usart_data *const data = dev->data;
259+
260+
data->user_cb = cb;
261+
data->user_data = user_data;
262+
}
263+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
264+
127265
static const struct uart_driver_api usart_gd32_driver_api = {
128266
.poll_in = usart_gd32_poll_in,
129267
.poll_out = usart_gd32_poll_out,
130268
.err_check = usart_gd32_err_check,
269+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
270+
.fifo_fill = usart_gd32_fifo_fill,
271+
.fifo_read = usart_gd32_fifo_read,
272+
.irq_tx_enable = usart_gd32_irq_tx_enable,
273+
.irq_tx_disable = usart_gd32_irq_tx_disable,
274+
.irq_tx_ready = usart_gd32_irq_tx_ready,
275+
.irq_tx_complete = usart_gd32_irq_tx_complete,
276+
.irq_rx_enable = usart_gd32_irq_rx_enable,
277+
.irq_rx_disable = usart_gd32_irq_rx_disable,
278+
.irq_rx_ready = usart_gd32_irq_rx_ready,
279+
.irq_err_enable = usart_gd32_irq_err_enable,
280+
.irq_err_disable = usart_gd32_irq_err_disable,
281+
.irq_is_pending = usart_gd32_irq_is_pending,
282+
.irq_callback_set = usart_gd32_irq_callback_set,
283+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
131284
};
132285

286+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
287+
#define GD32_USART_IRQ_HANDLER(n) \
288+
static void usart_gd32_config_func_##n(const struct device *dev) \
289+
{ \
290+
IRQ_CONNECT(DT_INST_IRQN(n), \
291+
DT_INST_IRQ(n, priority), \
292+
usart_gd32_isr, \
293+
DEVICE_DT_INST_GET(n), \
294+
0); \
295+
irq_enable(DT_INST_IRQN(n)); \
296+
}
297+
#define GD32_USART_IRQ_HANDLER_FUNC_INIT(n) \
298+
.irq_config_func = usart_gd32_config_func_##n
299+
#else /* CONFIG_UART_INTERRUPT_DRIVEN */
300+
#define GD32_USART_IRQ_HANDLER(n)
301+
#define GD32_USART_IRQ_HANDLER_FUNC_INIT(n)
302+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
303+
133304
#define GD32_USART_INIT(n) \
134305
PINCTRL_DT_INST_DEFINE(n) \
135-
static struct gd32_usart_data usart##n##_gd32_data = { \
306+
GD32_USART_IRQ_HANDLER(n) \
307+
static struct gd32_usart_data usart_gd32_data_##n = { \
136308
.baud_rate = DT_INST_PROP(n, current_speed), \
137309
}; \
138-
static const struct gd32_usart_config usart##n##_gd32_config = { \
310+
static const struct gd32_usart_config usart_gd32_config_##n = { \
139311
.reg = DT_INST_REG_ADDR(n), \
140312
.rcu_periph_clock = DT_INST_PROP(n, rcu_periph_clock), \
141313
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
142314
.parity = DT_ENUM_IDX_OR(DT_DRV_INST(n), parity, \
143315
UART_CFG_PARITY_NONE), \
316+
GD32_USART_IRQ_HANDLER_FUNC_INIT(n) \
144317
}; \
145318
DEVICE_DT_INST_DEFINE(n, &usart_gd32_init, \
146319
NULL, \
147-
&usart##n##_gd32_data, \
148-
&usart##n##_gd32_config, PRE_KERNEL_1, \
149-
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
320+
&usart_gd32_data_##n, \
321+
&usart_gd32_config_##n, PRE_KERNEL_1, \
322+
CONFIG_SERIAL_INIT_PRIORITY, \
150323
&usart_gd32_driver_api);
151324

152325
DT_INST_FOREACH_STATUS_OKAY(GD32_USART_INIT)

dts/arm/gigadevice/gd32f403/gd32f403.dtsi

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,51 @@
4646
};
4747
};
4848

49+
usart0: usart@40013800 {
50+
compatible = "gd,gd32-usart";
51+
reg = <0x40013800 0x400>;
52+
interrupts = <37 0>;
53+
rcu-periph-clock = <0x60e>;
54+
status = "disabled";
55+
label = "USART_0";
56+
};
57+
58+
usart1: usart@40004400 {
59+
compatible = "gd,gd32-usart";
60+
reg = <0x40004400 0x400>;
61+
interrupts = <38 0>;
62+
rcu-periph-clock = <0x712>;
63+
status = "disabled";
64+
label = "USART_1";
65+
};
66+
67+
usart2: usart@40004800 {
68+
compatible = "gd,gd32-usart";
69+
reg = <0x40004800 0x400>;
70+
interrupts = <39 0>;
71+
rcu-periph-clock = <0x713>;
72+
status = "disabled";
73+
label = "USART_2";
74+
};
75+
76+
uart3: usart@40004C00 {
77+
compatible = "gd,gd32-usart";
78+
reg = <0x40004C00 0x400>;
79+
interrupts = <52 0>;
80+
rcu-periph-clock = <0x714>;
81+
status = "disabled";
82+
label = "USART_3";
83+
};
84+
85+
uart4: usart@40005000 {
86+
compatible = "gd,gd32-usart";
87+
reg = <0x40005000 0x400>;
88+
interrupts = <53 0>;
89+
rcu-periph-clock = <0x715>;
90+
status = "disabled";
91+
label = "USART_4";
92+
};
93+
4994
afio: afio@40010000 {
5095
compatible = "gd,gd32-afio";
5196
reg = <0x40010000 0x400>;
@@ -119,13 +164,6 @@
119164
};
120165
};
121166

122-
usart0: usart@40013800 {
123-
compatible = "gd,gd32-usart";
124-
reg = <0x40013800 0x400>;
125-
rcu-periph-clock = <0x60e>;
126-
status = "disabled";
127-
label = "usart_0";
128-
};
129167
};
130168
};
131169

dts/arm/gigadevice/gd32f4xx/gd32f4xx.dtsi

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,73 @@
4949
usart0: usart@40011000 {
5050
compatible = "gd,gd32-usart";
5151
reg = <0x40011000 0x400>;
52+
interrupts = <37 0>;
5253
rcu-periph-clock = <0x1104>;
5354
status = "disabled";
54-
label = "USART0";
55+
label = "USART_0";
56+
};
57+
58+
usart1: usart@40004400 {
59+
compatible = "gd,gd32-usart";
60+
reg = <0x40004400 0x400>;
61+
interrupts = <38 0>;
62+
rcu-periph-clock = <0x1011>;
63+
status = "disabled";
64+
label = "USART_1";
65+
};
66+
67+
usart2: usart@40004800 {
68+
compatible = "gd,gd32-usart";
69+
reg = <0x40004800 0x400>;
70+
interrupts = <39 0>;
71+
rcu-periph-clock = <0x1012>;
72+
status = "disabled";
73+
label = "USART_2";
74+
};
75+
76+
uart3: usart@40004c00 {
77+
compatible = "gd,gd32-usart";
78+
reg = <0x40004c00 0x400>;
79+
interrupts = <52 0>;
80+
rcu-periph-clock = <0x1013>;
81+
status = "disabled";
82+
label = "USART_3";
83+
};
84+
85+
uart4: usart@40005000 {
86+
compatible = "gd,gd32-usart";
87+
reg = <0x40005000 0x400>;
88+
interrupts = <52 0>;
89+
rcu-periph-clock = <0x1014>;
90+
status = "disabled";
91+
label = "USART_4";
92+
};
93+
94+
usart5: usart@40011400 {
95+
compatible = "gd,gd32-usart";
96+
reg = <0x40011400 0x400>;
97+
interrupts = <71 0>;
98+
rcu-periph-clock = <0x1105>;
99+
status = "disabled";
100+
label = "USART_5";
101+
};
102+
103+
uart6: usart@40007800 {
104+
compatible = "gd,gd32-usart";
105+
reg = <0x40007800 0x400>;
106+
interrupts = <82 0>;
107+
rcu-periph-clock = <0x101e>;
108+
status = "disabled";
109+
label = "USART_6";
110+
};
111+
112+
uart7: usart@40007c00 {
113+
compatible = "gd,gd32-usart";
114+
reg = <0x40007c00 0x400>;
115+
interrupts = <83 0>;
116+
rcu-periph-clock = <0x101f>;
117+
status = "disabled";
118+
label = "USART_7";
55119
};
56120

57121
pinctrl: pin-controller@40020000 {

dts/bindings/serial/gd,gd32-usart.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ properties:
1111
reg:
1212
required: true
1313

14+
interrupts:
15+
required: true
16+
1417
rcu-periph-clock:
1518
type: int
1619
description: Reset Control Unit Peripheral Clock ID

0 commit comments

Comments
 (0)