Skip to content

Commit ab952c0

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 ab952c0

File tree

2 files changed

+190
-2
lines changed

2 files changed

+190
-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: 189 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

@@ -35,11 +37,21 @@
3537
/* minimal BRR: INT=1, FRAC=0 (0x10) */
3638
#define UART_BRR_MIN 0x10U
3739

40+
struct uart_sf32lb_data {
41+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
42+
uart_irq_callback_user_data_t irq_callback;
43+
void *cb_data;
44+
#endif
45+
};
46+
3847
struct uart_sf32lb_config {
3948
uintptr_t base;
4049
const struct pinctrl_dev_config *pcfg;
4150
struct sf32lb_clock_dt_spec clock;
4251
struct uart_config uart_cfg;
52+
#if CONFIG_UART_INTERRUPT_DRIVEN
53+
void (*irq_config_func)(const struct device *dev);
54+
#endif
4355
};
4456

4557
static int uart_sf32lb_configure(const struct device *dev, const struct uart_config *cfg)
@@ -177,9 +189,143 @@ static void uart_sf32lb_poll_out(const struct device *dev, uint8_t c)
177189
}
178190
}
179191

192+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
193+
static int uart_sf32lb_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len)
194+
{
195+
const struct uart_sf32lb_config *config = dev->config;
196+
int i;
197+
198+
for (i = 0; i < len; i++) {
199+
if ((sys_read32(config->base + UART_ISR) & USART_ISR_TXE) == 0U) {
200+
break;
201+
}
202+
sys_write8(tx_data[i], config->base + UART_TDR);
203+
}
204+
205+
return i;
206+
}
207+
208+
static int uart_sf32lb_fifo_read(const struct device *dev, uint8_t *rx_data, const int size)
209+
{
210+
const struct uart_sf32lb_config *config = dev->config;
211+
int i;
212+
213+
for (i = 0; i < size; i++) {
214+
if ((sys_read32(config->base + UART_ISR) & USART_ISR_RXNE) == 0U) {
215+
break;
216+
}
217+
rx_data[i] = sys_read32(config->base + UART_RDR) & 0xFF;
218+
}
219+
220+
return i;
221+
}
222+
223+
static void uart_sf32lb_irq_tx_enable(const struct device *dev)
224+
{
225+
const struct uart_sf32lb_config *config = dev->config;
226+
227+
sys_set_bit(config->base + UART_CR1, USART_CR1_TE_Pos);
228+
}
229+
230+
static void uart_sf32lb_irq_tx_disable(const struct device *dev)
231+
{
232+
const struct uart_sf32lb_config *config = dev->config;
233+
234+
sys_clear_bit(config->base + UART_CR1, USART_CR1_TE_Pos);
235+
}
236+
237+
static int uart_sf32lb_irq_tx_ready(const struct device *dev)
238+
{
239+
const struct uart_sf32lb_config *config = dev->config;
240+
241+
return ((sys_read32(config->base + UART_ISR) & USART_ISR_TXE) == USART_ISR_TXE);
242+
}
243+
244+
static int uart_sf32lb_irq_tx_complete(const struct device *dev)
245+
{
246+
const struct uart_sf32lb_config *config = dev->config;
247+
248+
return ((sys_read32(config->base + UART_ISR) & USART_ISR_TC) == USART_ISR_TC);
249+
}
250+
251+
static int uart_sf32lb_irq_rx_ready(const struct device *dev)
252+
{
253+
const struct uart_sf32lb_config *config = dev->config;
254+
255+
return ((sys_read32(config->base + UART_ISR) & USART_ISR_RXNE) == USART_ISR_RXNE);
256+
}
257+
258+
static void uart_sf32lb_irq_err_enable(const struct device *dev)
259+
{
260+
const struct uart_sf32lb_config *config = dev->config;
261+
262+
sys_set_bit(config->base + UART_CR1, USART_CR1_PEIE_Pos);
263+
sys_set_bit(config->base + UART_CR3, USART_CR3_EIE_Pos);
264+
}
265+
266+
static void uart_sf32lb_irq_err_disable(const struct device *dev)
267+
{
268+
const struct uart_sf32lb_config *config = dev->config;
269+
270+
sys_clear_bit(config->base + UART_CR1, USART_CR1_PEIE_Pos);
271+
sys_clear_bit(config->base + UART_CR3, USART_CR3_EIE_Pos);
272+
}
273+
274+
static int uart_sf32lb_irq_is_pending(const struct device *dev)
275+
{
276+
const struct uart_sf32lb_config *config = dev->config;
277+
278+
return sys_read32(config->base + UART_ISR);
279+
}
280+
281+
static int uart_sf32lb_irq_update(const struct device *dev)
282+
{
283+
return 1;
284+
}
285+
286+
static void uart_sf32lb_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb,
287+
void *user_data)
288+
{
289+
struct uart_sf32lb_data *data = dev->data;
290+
291+
data->irq_callback = cb;
292+
data->cb_data = user_data;
293+
}
294+
295+
static void uart_sf32lb_irq_rx_enable(const struct device *dev)
296+
{
297+
const struct uart_sf32lb_config *config = dev->config;
298+
299+
sys_set_bit(config->base + UART_CR3, USART_ISR_RXNE);
300+
}
301+
302+
static void uart_sf32lb_irq_rx_disable(const struct device *dev)
303+
{
304+
const struct uart_sf32lb_config *config = dev->config;
305+
306+
sys_clear_bit(config->base + UART_CR3, USART_ISR_RXNE);
307+
}
308+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
309+
180310
static const struct uart_driver_api uart_sf32lb_api = {
181311
.poll_in = uart_sf32lb_poll_in,
182312
.poll_out = uart_sf32lb_poll_out,
313+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
314+
.fifo_fill = uart_sf32lb_fifo_fill,
315+
.fifo_read = uart_sf32lb_fifo_read,
316+
.irq_tx_enable = uart_sf32lb_irq_tx_enable,
317+
.irq_tx_disable = uart_sf32lb_irq_tx_disable,
318+
.irq_tx_complete = uart_sf32lb_irq_tx_complete,
319+
.irq_tx_ready = uart_sf32lb_irq_tx_ready,
320+
.irq_rx_enable = uart_sf32lb_irq_rx_enable,
321+
.irq_rx_disable = uart_sf32lb_irq_rx_disable,
322+
.irq_rx_ready = uart_sf32lb_irq_rx_ready,
323+
.irq_err_enable = uart_sf32lb_irq_err_enable,
324+
.irq_err_disable = uart_sf32lb_irq_err_disable,
325+
.irq_is_pending = uart_sf32lb_irq_is_pending,
326+
.irq_update = uart_sf32lb_irq_update,
327+
.irq_callback_set = uart_sf32lb_irq_callback_set,
328+
#endif
183329
};
184330

185331
static int uart_sf32lb_init(const struct device *dev)
@@ -208,10 +354,45 @@ static int uart_sf32lb_init(const struct device *dev)
208354
return ret;
209355
}
210356

357+
#if CONFIG_UART_INTERRUPT_DRIVEN
358+
config->irq_config_func(dev);
359+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
360+
211361
return 0;
212362
}
213363

364+
#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
365+
static void uart_sf32lb_isr(const struct device *dev)
366+
{
367+
struct uart_sf32lb_data *data = dev->data;
368+
369+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
370+
if (data->irq_callback) {
371+
data->irq_callback(dev, data->cb_data);
372+
}
373+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
374+
}
375+
376+
#define SF32LB_UART_IRQ_HANDLER_DECL(index) \
377+
static void uart_sf32lb_irq_config_func_##index(const struct device *dev);
378+
379+
#define SF32LB_UART_IRQ_HANDLER(index) \
380+
static void uart_sf32lb_irq_config_func_##index(const struct device *dev) \
381+
{ \
382+
IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), uart_sf32lb_isr, \
383+
DEVICE_DT_INST_GET(index), 0); \
384+
irq_enable(DT_INST_IRQN(index)); \
385+
}
386+
387+
#define SF32LB_UART_IRQ_HANDLER_FUNC(index) .irq_config_func = uart_sf32lb_irq_config_func_##index,
388+
#else
389+
#define SF32LB_UART_IRQ_HANDLER_DECL(index)
390+
#define SF32LB_UART_IRQ_HANDLER(index)
391+
#define SF32LB_UART_IRQ_HANDLER_FUNC(index)
392+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
393+
214394
#define SF32LB_UART_DEFINE(index) \
395+
SF32LB_UART_IRQ_HANDLER_DECL(index) \
215396
PINCTRL_DT_INST_DEFINE(index); \
216397
\
217398
static const struct uart_sf32lb_config uart_sf32lb_cfg_##index = { \
@@ -231,9 +412,15 @@ static int uart_sf32lb_init(const struct device *dev)
231412
? UART_CFG_FLOW_CTRL_RTS_CTS \
232413
: UART_CFG_FLOW_CTRL_NONE, \
233414
}, \
415+
SF32LB_UART_IRQ_HANDLER_FUNC(index) \
234416
}; \
235417
\
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);
418+
static struct uart_sf32lb_data uart_sf32lb_data_##index; \
419+
\
420+
DEVICE_DT_INST_DEFINE(index, uart_sf32lb_init, NULL, \
421+
&uart_sf32lb_data_##index, &uart_sf32lb_cfg_##index, PRE_KERNEL_1, \
422+
CONFIG_SERIAL_INIT_PRIORITY, &uart_sf32lb_api); \
423+
\
424+
SF32LB_UART_IRQ_HANDLER(index)
238425

239426
DT_INST_FOREACH_STATUS_OKAY(SF32LB_UART_DEFINE)

0 commit comments

Comments
 (0)