Skip to content

Commit 5a65c86

Browse files
nhutnguyenkckartben
authored andcommitted
drivers: serial: Add interrupt-driven API support for RZ/G3S
This commit is to support UART interrupt-driven API for Renesas RZ/G3S. Signed-off-by: Nhut Nguyen <nhut.nguyen.kc@renesas.com>
1 parent 2615ec8 commit 5a65c86

File tree

2 files changed

+257
-26
lines changed

2 files changed

+257
-26
lines changed

drivers/serial/Kconfig.renesas_rz

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

drivers/serial/uart_renesas_rz_scif.c

Lines changed: 256 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <zephyr/drivers/pinctrl.h>
99
#include <zephyr/drivers/uart.h>
1010
#include <zephyr/logging/log.h>
11+
#include <zephyr/irq.h>
1112
#include "r_scif_uart.h"
1213

1314
LOG_MODULE_REGISTER(rz_scif_uart);
@@ -17,12 +18,36 @@ struct uart_rz_scif_config {
1718
const uart_api_t *fsp_api;
1819
};
1920

21+
struct uart_rz_scif_int {
22+
bool rxi_flag;
23+
bool tei_flag;
24+
bool rx_fifo_busy;
25+
bool irq_rx_enable;
26+
bool irq_tx_enable;
27+
uint8_t rx_byte;
28+
uint8_t tx_byte;
29+
uart_event_t event;
30+
};
31+
2032
struct uart_rz_scif_data {
2133
struct uart_config uart_config;
2234
uart_cfg_t *fsp_cfg;
35+
struct uart_rz_scif_int int_data;
2336
scif_uart_instance_ctrl_t *fsp_ctrl;
37+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
38+
uart_irq_callback_user_data_t callback;
39+
void *callback_data;
40+
#endif
2441
};
2542

43+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
44+
void scif_uart_rxi_isr(void);
45+
void scif_uart_txi_isr(void);
46+
void scif_uart_tei_isr(void);
47+
void scif_uart_eri_isr(void);
48+
void scif_uart_bri_isr(void);
49+
#endif
50+
2651
static int uart_rz_scif_poll_in(const struct device *dev, unsigned char *c)
2752
{
2853
struct uart_rz_scif_data *data = dev->data;
@@ -41,6 +66,9 @@ static void uart_rz_scif_poll_out(const struct device *dev, unsigned char c)
4166
{
4267
struct uart_rz_scif_data *data = dev->data;
4368
R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
69+
uint8_t key;
70+
71+
key = irq_lock();
4472

4573
while (!reg->FSR_b.TDFE) {
4674
}
@@ -49,28 +77,27 @@ static void uart_rz_scif_poll_out(const struct device *dev, unsigned char c)
4977

5078
while (!reg->FSR_b.TEND) {
5179
}
80+
81+
irq_unlock(key);
5282
}
5383

5484
static int uart_rz_scif_err_check(const struct device *dev)
5585
{
5686
struct uart_rz_scif_data *data = dev->data;
57-
R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
87+
uart_event_t event = data->int_data.event;
88+
int err = 0;
5889

59-
const uint32_t fsr = reg->FSR;
60-
const uint32_t lsr = reg->LSR;
61-
int errors = 0;
62-
63-
if ((lsr & R_SCIFA0_LSR_ORER_Msk) != 0) {
64-
errors |= UART_ERROR_OVERRUN;
90+
if (event & UART_EVENT_ERR_OVERFLOW) {
91+
err |= UART_ERROR_OVERRUN;
6592
}
66-
if ((fsr & R_SCIFA0_FSR_PER_Msk) != 0) {
67-
errors |= UART_ERROR_PARITY;
93+
if (event & UART_EVENT_ERR_FRAMING) {
94+
err |= UART_ERROR_FRAMING;
6895
}
69-
if ((fsr & R_SCIFA0_FSR_FER_Pos) != 0) {
70-
errors |= UART_ERROR_FRAMING;
96+
if (event & UART_EVENT_ERR_PARITY) {
97+
err |= UART_ERROR_PARITY;
7198
}
7299

73-
return errors;
100+
return err;
74101
}
75102

76103
static int uart_rz_scif_apply_config(const struct device *dev)
@@ -179,11 +206,6 @@ static int uart_rz_scif_configure(const struct device *dev, const struct uart_co
179206
return -EIO;
180207
}
181208

182-
R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
183-
/* Temporarily disable the DRI interrupt caused by receive data ready */
184-
/* TODO: support interrupt-driven api */
185-
reg->SCR_b.RIE = 0;
186-
187209
return err;
188210
}
189211

@@ -197,6 +219,187 @@ static int uart_rz_scif_config_get(const struct device *dev, struct uart_config
197219

198220
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
199221

222+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
223+
224+
static int uart_rz_scif_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size)
225+
{
226+
struct uart_rz_scif_data *data = dev->data;
227+
scif_uart_instance_ctrl_t *fsp_ctrl = data->fsp_ctrl;
228+
229+
fsp_ctrl->tx_src_bytes = size;
230+
fsp_ctrl->p_tx_src = tx_data;
231+
232+
scif_uart_txi_isr();
233+
234+
return (size - fsp_ctrl->tx_src_bytes);
235+
}
236+
237+
static int uart_rz_scif_fifo_read(const struct device *dev, uint8_t *rx_data, const int size)
238+
{
239+
struct uart_rz_scif_data *data = dev->data;
240+
241+
scif_uart_instance_ctrl_t *fsp_ctrl = data->fsp_ctrl;
242+
243+
fsp_ctrl->rx_dest_bytes = size;
244+
fsp_ctrl->p_rx_dest = rx_data;
245+
246+
/* Read all available data in the FIFO */
247+
/* If there are more available data than required, they will be lost */
248+
if (data->int_data.rxi_flag) {
249+
scif_uart_rxi_isr();
250+
} else {
251+
scif_uart_tei_isr();
252+
}
253+
254+
data->int_data.rx_fifo_busy = false;
255+
256+
return (size - fsp_ctrl->rx_dest_bytes);
257+
}
258+
259+
static void uart_rz_scif_irq_rx_enable(const struct device *dev)
260+
{
261+
const struct uart_rz_scif_config *config = dev->config;
262+
struct uart_rz_scif_data *data = dev->data;
263+
264+
data->int_data.irq_rx_enable = true;
265+
266+
/* Prepare 1-byte buffer to receive, it will be overwritten by fifo read */
267+
config->fsp_api->read(data->fsp_ctrl, &(data->int_data.rx_byte), 1);
268+
}
269+
270+
static void uart_rz_scif_irq_rx_disable(const struct device *dev)
271+
{
272+
struct uart_rz_scif_data *data = dev->data;
273+
274+
data->int_data.irq_rx_enable = false;
275+
data->int_data.rx_fifo_busy = false;
276+
}
277+
278+
static void uart_rz_scif_irq_tx_enable(const struct device *dev)
279+
{
280+
struct uart_rz_scif_data *data = dev->data;
281+
const struct uart_rz_scif_config *config = dev->config;
282+
283+
data->int_data.irq_tx_enable = true;
284+
285+
/* Trigger TX with a NULL frame */
286+
/* It is expected not to be sent, and will be overwritten by the fifo fill */
287+
data->int_data.tx_byte = '\0';
288+
config->fsp_api->write(data->fsp_ctrl, &data->int_data.tx_byte, 1);
289+
}
290+
291+
static void uart_rz_scif_irq_tx_disable(const struct device *dev)
292+
{
293+
struct uart_rz_scif_data *data = dev->data;
294+
295+
data->int_data.irq_tx_enable = false;
296+
}
297+
298+
static int uart_rz_scif_irq_tx_ready(const struct device *dev)
299+
{
300+
struct uart_rz_scif_data *data = dev->data;
301+
302+
return data->int_data.irq_tx_enable;
303+
}
304+
305+
static int uart_rz_scif_irq_rx_ready(const struct device *dev)
306+
{
307+
struct uart_rz_scif_data *data = dev->data;
308+
309+
return data->int_data.rx_fifo_busy && data->int_data.irq_rx_enable;
310+
}
311+
312+
static int uart_rz_scif_irq_is_pending(const struct device *dev)
313+
{
314+
return (uart_rz_scif_irq_tx_ready(dev)) || (uart_rz_scif_irq_rx_ready(dev));
315+
}
316+
317+
static void uart_rz_scif_irq_callback_set(const struct device *dev,
318+
uart_irq_callback_user_data_t cb, void *cb_data)
319+
{
320+
struct uart_rz_scif_data *data = dev->data;
321+
322+
data->callback = cb;
323+
data->callback_data = cb_data;
324+
}
325+
326+
static int uart_rz_scif_irq_update(const struct device *dev)
327+
{
328+
ARG_UNUSED(dev);
329+
return 1;
330+
}
331+
332+
static void uart_rz_scif_rxi_isr(const struct device *dev)
333+
{
334+
struct uart_rz_scif_data *data = dev->data;
335+
336+
data->int_data.rxi_flag = true;
337+
data->int_data.rx_fifo_busy = true;
338+
if (data->callback) {
339+
data->callback(dev, data->callback_data);
340+
}
341+
}
342+
343+
static void uart_rz_scif_txi_isr(const struct device *dev)
344+
{
345+
struct uart_rz_scif_data *data = dev->data;
346+
347+
data->int_data.tei_flag = false;
348+
if (data->callback) {
349+
data->callback(dev, data->callback_data);
350+
}
351+
}
352+
353+
static void uart_rz_scif_tei_isr(const struct device *dev)
354+
{
355+
struct uart_rz_scif_data *data = dev->data;
356+
357+
if (data->int_data.tei_flag) {
358+
scif_uart_tei_isr();
359+
} else {
360+
data->int_data.rxi_flag = false;
361+
data->int_data.rx_fifo_busy = true;
362+
if (data->callback) {
363+
data->callback(dev, data->callback_data);
364+
}
365+
}
366+
}
367+
368+
static void uart_rz_scif_eri_isr(const struct device *dev)
369+
{
370+
scif_uart_eri_isr();
371+
}
372+
373+
static void uart_rz_scif_bri_isr(const struct device *dev)
374+
{
375+
scif_uart_bri_isr();
376+
}
377+
378+
static void uart_rz_scif_event_handler(uart_callback_args_t *p_args)
379+
{
380+
const struct device *dev = (const struct device *)p_args->p_context;
381+
struct uart_rz_scif_data *data = dev->data;
382+
383+
data->int_data.event = p_args->event;
384+
switch (p_args->event) {
385+
case UART_EVENT_RX_CHAR:
386+
data->int_data.rx_byte = p_args->data;
387+
break;
388+
case UART_EVENT_RX_COMPLETE:
389+
break;
390+
case UART_EVENT_TX_DATA_EMPTY:
391+
data->int_data.tei_flag = true;
392+
break;
393+
case UART_EVENT_TX_COMPLETE:
394+
data->int_data.tei_flag = false;
395+
break;
396+
default:
397+
break;
398+
}
399+
}
400+
401+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
402+
200403
static DEVICE_API(uart, uart_rz_scif_driver_api) = {
201404
.poll_in = uart_rz_scif_poll_in,
202405
.poll_out = uart_rz_scif_poll_out,
@@ -205,6 +408,19 @@ static DEVICE_API(uart, uart_rz_scif_driver_api) = {
205408
.configure = uart_rz_scif_configure,
206409
.config_get = uart_rz_scif_config_get,
207410
#endif
411+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
412+
.fifo_fill = uart_rz_scif_fifo_fill,
413+
.fifo_read = uart_rz_scif_fifo_read,
414+
.irq_rx_enable = uart_rz_scif_irq_rx_enable,
415+
.irq_rx_disable = uart_rz_scif_irq_rx_disable,
416+
.irq_tx_enable = uart_rz_scif_irq_tx_enable,
417+
.irq_tx_disable = uart_rz_scif_irq_tx_disable,
418+
.irq_tx_ready = uart_rz_scif_irq_tx_ready,
419+
.irq_rx_ready = uart_rz_scif_irq_rx_ready,
420+
.irq_is_pending = uart_rz_scif_irq_is_pending,
421+
.irq_callback_set = uart_rz_scif_irq_callback_set,
422+
.irq_update = uart_rz_scif_irq_update,
423+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
208424
};
209425

210426
static int uart_rz_scif_init(const struct device *dev)
@@ -227,14 +443,24 @@ static int uart_rz_scif_init(const struct device *dev)
227443

228444
config->fsp_api->open(data->fsp_ctrl, data->fsp_cfg);
229445

230-
R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
231-
/* Temporarily disable the DRI interrupt caused by receive data ready */
232-
/* TODO: support interrupt-driven api */
233-
reg->SCR_b.RIE = 0;
234-
235446
return 0;
236447
}
237448

449+
#define UART_RZG_IRQ_CONNECT(n, irq_name, isr) \
450+
do { \
451+
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, irq_name, irq), \
452+
DT_INST_IRQ_BY_NAME(n, irq_name, priority), isr, \
453+
DEVICE_DT_INST_GET(n), 0); \
454+
irq_enable(DT_INST_IRQ_BY_NAME(n, irq_name, irq)); \
455+
} while (0)
456+
457+
#define UART_RZG_CONFIG_FUNC(n) \
458+
UART_RZG_IRQ_CONNECT(n, eri, uart_rz_scif_eri_isr); \
459+
UART_RZG_IRQ_CONNECT(n, rxi, uart_rz_scif_rxi_isr); \
460+
UART_RZG_IRQ_CONNECT(n, txi, uart_rz_scif_txi_isr); \
461+
UART_RZG_IRQ_CONNECT(n, tei, uart_rz_scif_tei_isr); \
462+
UART_RZG_IRQ_CONNECT(n, bri, uart_rz_scif_bri_isr);
463+
238464
#define UART_RZG_INIT(n) \
239465
static scif_uart_instance_ctrl_t g_uart##n##_ctrl; \
240466
static scif_baud_setting_t g_uart##n##_baud_setting; \
@@ -258,8 +484,6 @@ static int uart_rz_scif_init(const struct device *dev)
258484
}; \
259485
static uart_cfg_t g_uart##n##_cfg = { \
260486
.channel = DT_INST_PROP(n, channel), \
261-
.p_callback = NULL, \
262-
.p_context = NULL, \
263487
.p_extend = &g_uart##n##_cfg_extend, \
264488
.p_transfer_tx = NULL, \
265489
.p_transfer_rx = NULL, \
@@ -271,10 +495,14 @@ static int uart_rz_scif_init(const struct device *dev)
271495
.txi_irq = DT_INST_IRQ_BY_NAME(n, txi, irq), \
272496
.tei_irq = DT_INST_IRQ_BY_NAME(n, tei, irq), \
273497
.eri_irq = DT_INST_IRQ_BY_NAME(n, eri, irq), \
274-
}; \
498+
IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, ( \
499+
.p_callback = uart_rz_scif_event_handler, \
500+
.p_context = (void *)DEVICE_DT_INST_GET(n),)) }; \
275501
PINCTRL_DT_INST_DEFINE(n); \
276502
static const struct uart_rz_scif_config uart_rz_scif_config_##n = { \
277-
.pin_config = PINCTRL_DT_INST_DEV_CONFIG_GET(n), .fsp_api = &g_uart_on_scif}; \
503+
.pin_config = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
504+
.fsp_api = &g_uart_on_scif, \
505+
}; \
278506
static struct uart_rz_scif_data uart_rz_scif_data_##n = { \
279507
.uart_config = \
280508
{ \
@@ -290,6 +518,8 @@ static int uart_rz_scif_init(const struct device *dev)
290518
}; \
291519
static int uart_rz_scif_init_##n(const struct device *dev) \
292520
{ \
521+
IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
522+
(UART_RZG_CONFIG_FUNC(n);)) \
293523
return uart_rz_scif_init(dev); \
294524
} \
295525
DEVICE_DT_INST_DEFINE(n, &uart_rz_scif_init_##n, NULL, &uart_rz_scif_data_##n, \

0 commit comments

Comments
 (0)