Skip to content

Commit c6b3a82

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 c6b3a82

File tree

2 files changed

+211
-2
lines changed

2 files changed

+211
-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: 210 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,6 +12,7 @@
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

@@ -32,16 +34,71 @@
3234
#define UART_CR2_STOP_1B FIELD_PREP(USART_CR2_STOP_Msk, 0U)
3335
#define UART_CR2_STOP_2B FIELD_PREP(USART_CR2_STOP_Msk, 1U)
3436

37+
#define UART_FLAG_IS_SET(reg, flag) \
38+
sys_test_bit(reg, flag)
39+
40+
#define UART_FLAG_CLEAR(reg, flag) \
41+
sys_clear_bit(reg, flag)
42+
3543
/* minimal BRR: INT=1, FRAC=0 (0x10) */
3644
#define UART_BRR_MIN 0x10U
3745

46+
struct uart_sf32lb_data {
47+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
48+
uart_irq_callback_user_data_t irq_callback;
49+
void *cb_data;
50+
#endif
51+
};
52+
3853
struct uart_sf32lb_config {
3954
uintptr_t base;
4055
const struct pinctrl_dev_config *pcfg;
4156
struct sf32lb_clock_dt_spec clock;
4257
struct uart_config uart_cfg;
58+
#if CONFIG_UART_INTERRUPT_DRIVEN
59+
void (*irq_config_func)(const struct device *dev);
60+
#endif
4361
};
4462

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

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

185377
static int uart_sf32lb_init(const struct device *dev)
@@ -208,11 +400,22 @@ static int uart_sf32lb_init(const struct device *dev)
208400
return ret;
209401
}
210402

403+
#if CONFIG_UART_INTERRUPT_DRIVEN
404+
config->irq_config_func(dev);
405+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
406+
211407
return 0;
212408
}
213409

214410
#define SF32LB_UART_DEFINE(index) \
215411
PINCTRL_DT_INST_DEFINE(index); \
412+
IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
413+
(static void uart_sf32lb_irq_config_func_##index(const struct device *dev) \
414+
{ \
415+
IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), uart_sf32lb_isr, \
416+
DEVICE_DT_INST_GET(index), 0); \
417+
irq_enable(DT_INST_IRQN(index)); \
418+
})); \
216419
\
217420
static const struct uart_sf32lb_config uart_sf32lb_cfg_##index = { \
218421
.base = DT_INST_REG_ADDR(index), \
@@ -231,9 +434,14 @@ static int uart_sf32lb_init(const struct device *dev)
231434
? UART_CFG_FLOW_CTRL_RTS_CTS \
232435
: UART_CFG_FLOW_CTRL_NONE, \
233436
}, \
437+
IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
438+
(.irq_config_func = uart_sf32lb_irq_config_func_##index,)) \
234439
}; \
235440
\
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);
441+
static struct uart_sf32lb_data uart_sf32lb_data_##index; \
442+
\
443+
DEVICE_DT_INST_DEFINE(index, uart_sf32lb_init, NULL, \
444+
&uart_sf32lb_data_##index, &uart_sf32lb_cfg_##index, PRE_KERNEL_1, \
445+
CONFIG_SERIAL_INIT_PRIORITY, &uart_sf32lb_api);
238446

239447
DT_INST_FOREACH_STATUS_OKAY(SF32LB_UART_DEFINE)

0 commit comments

Comments
 (0)