Skip to content

Commit 04c7444

Browse files
committed
drivers: serial: sf32lb: add uart interrupt support
add sf32lb52x uart interrupt support Signed-off-by: Qingsong Gou <gouqs@hotmail.com>
1 parent 9dfac5a commit 04c7444

File tree

2 files changed

+206
-2
lines changed

2 files changed

+206
-2
lines changed

drivers/serial/Kconfig.sf32lb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ config UART_SF32LB
66
default y
77
depends on DT_HAS_SIFLI_SF32LB_USART_ENABLED
88
select SERIAL_HAS_DRIVER
9+
select SERIAL_SUPPORT_INTERRUPT
910
select PINCTRL
1011
select CLOCK_CONTROL
1112
help

drivers/serial/uart_sf32lb.c

Lines changed: 205 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) Core Devices LLC
3+
* Copyright (c) Qingsong Gou <gouqs@hotmail.com>
34
* SPDX-License-Identifier: Apache-2.0
45
*/
56

@@ -11,9 +12,12 @@
1112
#include <zephyr/drivers/clock_control/sf32lb.h>
1213
#include <zephyr/drivers/pinctrl.h>
1314
#include <zephyr/drivers/uart.h>
15+
#include <zephyr/irq.h>
1416

1517
#include <register.h>
1618

19+
#define UART_REG(reg) ((config->base) + (reg))
20+
1721
#define UART_CR1 offsetof(USART_TypeDef, CR1)
1822
#define UART_CR2 offsetof(USART_TypeDef, CR2)
1923
#define UART_CR3 offsetof(USART_TypeDef, CR3)
@@ -32,16 +36,71 @@
3236
#define UART_CR2_STOP_1B FIELD_PREP(USART_CR2_STOP_Msk, 0U)
3337
#define UART_CR2_STOP_2B FIELD_PREP(USART_CR2_STOP_Msk, 1U)
3438

39+
#define UART_FLAG_IS_SET(flag) \
40+
sys_test_bit(UART_REG(UART_ISR), flag)
41+
42+
#define UART_FLAG_CLEAR(flag) \
43+
sys_clear_bit(UART_REG(UART_ICR), flag)
44+
3545
/* minimal BRR: INT=1, FRAC=0 (0x10) */
3646
#define UART_BRR_MIN 0x10U
3747

48+
struct uart_sf32lb_data {
49+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
50+
uart_irq_callback_user_data_t irq_callback;
51+
void *cb_data;
52+
#endif
53+
};
54+
3855
struct uart_sf32lb_config {
3956
uintptr_t base;
4057
const struct pinctrl_dev_config *pcfg;
4158
struct sf32lb_clock_dt_spec clock;
4259
struct uart_config uart_cfg;
60+
#if CONFIG_UART_INTERRUPT_DRIVEN
61+
void (*irq_config_func)(const struct device *dev);
62+
#endif
4363
};
4464

65+
#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
66+
static void uart_sf32lb_isr(const struct device *dev)
67+
{
68+
const struct uart_sf32lb_config *config = dev->config;
69+
struct uart_sf32lb_data *data = dev->data;
70+
71+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
72+
if (data->irq_callback) {
73+
data->irq_callback(dev, data->cb_data);
74+
}
75+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
76+
if (UART_FLAG_IS_SET(USART_ISR_ORE_Pos)) {
77+
UART_FLAG_CLEAR(USART_ICR_ORECF_Pos);
78+
}
79+
if (UART_FLAG_IS_SET(USART_ISR_NF_Pos)) {
80+
UART_FLAG_CLEAR(USART_ICR_NCF_Pos);
81+
}
82+
if (UART_FLAG_IS_SET(USART_ISR_FE_Pos)) {
83+
UART_FLAG_CLEAR(USART_ICR_FECF_Pos);
84+
}
85+
if (UART_FLAG_IS_SET(USART_ISR_PE_Pos)) {
86+
UART_FLAG_CLEAR(USART_ICR_PECF_Pos);
87+
}
88+
89+
if (UART_FLAG_IS_SET(USART_ISR_CTS_Pos)) {
90+
UART_FLAG_CLEAR(USART_ISR_CTS_Pos);
91+
}
92+
if (UART_FLAG_IS_SET(USART_ISR_TXE_Pos)) {
93+
UART_FLAG_CLEAR(USART_ISR_TXE_Pos);
94+
}
95+
if (UART_FLAG_IS_SET(USART_ISR_TC_Pos)) {
96+
UART_FLAG_CLEAR(USART_ISR_TC_Pos);
97+
}
98+
if (UART_FLAG_IS_SET(USART_ISR_RXNE_Pos)) {
99+
UART_FLAG_CLEAR(USART_ISR_RXNE_Pos);
100+
}
101+
}
102+
#endif
103+
45104
static int uart_sf32lb_configure(const struct device *dev, const struct uart_config *cfg)
46105
{
47106
const struct uart_sf32lb_config *config = dev->config;
@@ -177,9 +236,137 @@ static void uart_sf32lb_poll_out(const struct device *dev, uint8_t c)
177236
}
178237
}
179238

239+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
240+
static int uart_sf32lb_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len)
241+
{
242+
const struct uart_sf32lb_config *config = dev->config;
243+
int i;
244+
245+
for (i = 0; i < len; i++) {
246+
if ((sys_read32(config->base + UART_ISR) & USART_ISR_TXE) == 0U) {
247+
break;
248+
}
249+
sys_write8(tx_data[i], config->base + UART_TDR);
250+
}
251+
252+
return i;
253+
}
254+
255+
static int uart_sf32lb_fifo_read(const struct device *dev, uint8_t *rx_data, const int size)
256+
{
257+
const struct uart_sf32lb_config *config = dev->config;
258+
int i;
259+
260+
for (i = 0; i < size; i++) {
261+
if ((sys_read32(config->base + UART_ISR) & USART_ISR_RXNE) == 0U) {
262+
break;
263+
}
264+
rx_data[i] = sys_read32(config->base + UART_RDR) & 0xFF;
265+
}
266+
267+
return i;
268+
}
269+
270+
static void uart_sf32lb_irq_tx_enable(const struct device *dev)
271+
{
272+
const struct uart_sf32lb_config *config = dev->config;
273+
274+
sys_set_bit(config->base + UART_CR1, USART_CR1_TE_Pos);
275+
}
276+
277+
static void uart_sf32lb_irq_tx_disable(const struct device *dev)
278+
{
279+
const struct uart_sf32lb_config *config = dev->config;
280+
281+
sys_clear_bit(config->base + UART_CR1, USART_CR1_TE_Pos);
282+
}
283+
284+
static int uart_sf32lb_irq_tx_ready(const struct device *dev)
285+
{
286+
const struct uart_sf32lb_config *config = dev->config;
287+
288+
return sys_test_bit(config->base + UART_ISR, USART_ISR_TXE_Pos);
289+
}
290+
291+
static int uart_sf32lb_irq_tx_complete(const struct device *dev)
292+
{
293+
const struct uart_sf32lb_config *config = dev->config;
294+
295+
return sys_test_bit(config->base + UART_ISR, USART_ISR_TC_Pos);
296+
}
297+
298+
static int uart_sf32lb_irq_rx_ready(const struct device *dev)
299+
{
300+
const struct uart_sf32lb_config *config = dev->config;
301+
302+
return sys_test_bit(config->base + UART_ISR, USART_ISR_RXNE_Pos);
303+
}
304+
305+
static void uart_sf32lb_irq_err_enable(const struct device *dev)
306+
{
307+
const struct uart_sf32lb_config *config = dev->config;
308+
309+
sys_set_bit(config->base + UART_CR1, USART_CR1_PEIE_Pos);
310+
sys_set_bit(config->base + UART_CR3, USART_CR3_EIE_Pos);
311+
}
312+
313+
static void uart_sf32lb_irq_err_disable(const struct device *dev)
314+
{
315+
const struct uart_sf32lb_config *config = dev->config;
316+
317+
sys_clear_bit(config->base + UART_CR1, USART_CR1_PEIE_Pos);
318+
sys_clear_bit(config->base + UART_CR3, USART_CR3_EIE_Pos);
319+
}
320+
321+
static int uart_sf32lb_irq_is_pending(const struct device *dev)
322+
{
323+
const struct uart_sf32lb_config *config = dev->config;
324+
325+
return sys_read32(config->base + UART_ISR) == 0U ? 0 : 1;
326+
}
327+
328+
static void uart_sf32lb_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb,
329+
void *user_data)
330+
{
331+
struct uart_sf32lb_data *data = dev->data;
332+
333+
data->irq_callback = cb;
334+
data->cb_data = user_data;
335+
}
336+
337+
static void uart_sf32lb_irq_rx_enable(const struct device *dev)
338+
{
339+
const struct uart_sf32lb_config *config = dev->config;
340+
341+
sys_set_bit(config->base + UART_CR3, USART_ISR_RXNE);
342+
}
343+
344+
static void uart_sf32lb_irq_rx_disable(const struct device *dev)
345+
{
346+
const struct uart_sf32lb_config *config = dev->config;
347+
348+
sys_clear_bit(config->base + UART_CR3, USART_ISR_RXNE);
349+
}
350+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
351+
180352
static const struct uart_driver_api uart_sf32lb_api = {
181353
.poll_in = uart_sf32lb_poll_in,
182354
.poll_out = uart_sf32lb_poll_out,
355+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
356+
.fifo_fill = uart_sf32lb_fifo_fill,
357+
.fifo_read = uart_sf32lb_fifo_read,
358+
.irq_tx_enable = uart_sf32lb_irq_tx_enable,
359+
.irq_tx_disable = uart_sf32lb_irq_tx_disable,
360+
.irq_tx_complete = uart_sf32lb_irq_tx_complete,
361+
.irq_tx_ready = uart_sf32lb_irq_tx_ready,
362+
.irq_rx_enable = uart_sf32lb_irq_rx_enable,
363+
.irq_rx_disable = uart_sf32lb_irq_rx_disable,
364+
.irq_rx_ready = uart_sf32lb_irq_rx_ready,
365+
.irq_err_enable = uart_sf32lb_irq_err_enable,
366+
.irq_err_disable = uart_sf32lb_irq_err_disable,
367+
.irq_is_pending = uart_sf32lb_irq_is_pending,
368+
.irq_callback_set = uart_sf32lb_irq_callback_set,
369+
#endif
183370
};
184371

185372
static int uart_sf32lb_init(const struct device *dev)
@@ -208,11 +395,22 @@ static int uart_sf32lb_init(const struct device *dev)
208395
return ret;
209396
}
210397

398+
#if CONFIG_UART_INTERRUPT_DRIVEN
399+
config->irq_config_func(dev);
400+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
401+
211402
return 0;
212403
}
213404

214405
#define SF32LB_UART_DEFINE(index) \
215406
PINCTRL_DT_INST_DEFINE(index); \
407+
IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
408+
(static void uart_sf32lb_irq_config_func_##index(const struct device *dev) \
409+
{ \
410+
IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), uart_sf32lb_isr, \
411+
DEVICE_DT_INST_GET(index), 0); \
412+
irq_enable(DT_INST_IRQN(index)); \
413+
})); \
216414
\
217415
static const struct uart_sf32lb_config uart_sf32lb_cfg_##index = { \
218416
.base = DT_INST_REG_ADDR(index), \
@@ -231,9 +429,14 @@ static int uart_sf32lb_init(const struct device *dev)
231429
? UART_CFG_FLOW_CTRL_RTS_CTS \
232430
: UART_CFG_FLOW_CTRL_NONE, \
233431
}, \
432+
IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
433+
(.irq_config_func = uart_sf32lb_irq_config_func_##index,)) \
234434
}; \
235435
\
236-
DEVICE_DT_INST_DEFINE(index, uart_sf32lb_init, NULL, NULL, &uart_sf32lb_cfg_##index, \
237-
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, &uart_sf32lb_api);
436+
static struct uart_sf32lb_data uart_sf32lb_data_##index; \
437+
\
438+
DEVICE_DT_INST_DEFINE(index, uart_sf32lb_init, NULL, \
439+
&uart_sf32lb_data_##index, &uart_sf32lb_cfg_##index, PRE_KERNEL_1, \
440+
CONFIG_SERIAL_INIT_PRIORITY, &uart_sf32lb_api);
238441

239442
DT_INST_FOREACH_STATUS_OKAY(SF32LB_UART_DEFINE)

0 commit comments

Comments
 (0)