From ffdf9a978d87bd845db1082a1df12a303d9657b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 21 Jun 2024 11:50:54 +0200 Subject: [PATCH] drivers: serial: nrfx_uarte: Use ENDTX_STOPTX short if possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use short which is available on some devices. Signed-off-by: Krzysztof Chruściński --- drivers/serial/Kconfig.nrfx_uart_instance | 2 +- drivers/serial/uart_nrfx_uarte.c | 52 +++++++++++++++-------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/serial/Kconfig.nrfx_uart_instance b/drivers/serial/Kconfig.nrfx_uart_instance index a1d62740b47..0840cad7760 100644 --- a/drivers/serial/Kconfig.nrfx_uart_instance +++ b/drivers/serial/Kconfig.nrfx_uart_instance @@ -20,7 +20,7 @@ config UART_$(nrfx_uart_num)_ASYNC config UART_$(nrfx_uart_num)_ENHANCED_POLL_OUT bool "Efficient poll out on port $(nrfx_uart_num)" - depends on !SOC_SERIES_NRF54LX + depends on !$(dt_nodelabel_has_prop,uart$(nrfx_uart_num),short-endtx-stoptx) default y depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) depends on HAS_HW_NRF_PPI || HAS_HW_NRF_DPPIC diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index f1c09844288..97edddbf278 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -39,9 +39,13 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #error "No PPI or DPPI" #endif +#define UARTE(idx) DT_NODELABEL(uart##idx) +#define UARTE_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(UARTE(idx), prop) +#define UARTE_PROP(idx, prop) DT_PROP(UARTE(idx), prop) + /* Execute macro f(x) for all instances. */ -#define UARTE_FOR_EACH_INSTANCE(f, sep, off_code) \ - NRFX_FOREACH_PRESENT(UARTE, f, sep, off_code, _) +#define UARTE_FOR_EACH_INSTANCE(f, sep, off_code, ...) \ + NRFX_FOREACH_PRESENT(UARTE, f, sep, off_code, __VA_ARGS__) /* Determine if any instance is using interrupt driven API. */ #define IS_INT_DRIVEN(unused, prefix, i, _) \ @@ -85,6 +89,15 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #define UARTE_ENHANCED_POLL_OUT 1 #endif +#define INSTANCE_PROP(unused, prefix, i, prop) UARTE_PROP(prefix##i, prop) +#define INSTANCE_PRESENT(unused, prefix, i, prop) 1 + +/* Driver supports case when all or none instances support that HW feature. */ +#if (UARTE_FOR_EACH_INSTANCE(INSTANCE_PROP, (+), (0), endtx_stoptx_supported)) == \ + (UARTE_FOR_EACH_INSTANCE(INSTANCE_PRESENT, (+), (0), endtx_stoptx_supported)) +#define UARTE_HAS_ENDTX_STOPTX_SHORT 1 +#endif + /* * RX timeout is divided into time slabs, this define tells how many divisions * should be made. More divisions - higher timeout accuracy and processor usage. @@ -269,7 +282,8 @@ static void uarte_nrfx_isr_int(const void *arg) /* If interrupt driven and asynchronous APIs are disabled then UART * interrupt is still called to stop TX. Unless it is done using PPI. */ - if (nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK) && + if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) && + nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK) && nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX)) { endtx_isr(dev); } @@ -455,7 +469,8 @@ static bool is_tx_ready(const struct device *dev) { const struct uarte_nrfx_config *config = dev->config; NRF_UARTE_Type *uarte = get_uarte_instance(dev); - bool ppi_endtx = config->flags & UARTE_CFG_FLAG_PPI_ENDTX; + bool ppi_endtx = config->flags & UARTE_CFG_FLAG_PPI_ENDTX || + IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT); return nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) || (!ppi_endtx ? @@ -1450,14 +1465,14 @@ static void uarte_nrfx_isr_async(const void *arg) rxto_isr(dev); } - if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX) - && nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK)) { + if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) && + (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX) && + nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK))) { endtx_isr(dev); } - if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) - && nrf_uarte_int_enable_check(uarte, - NRF_UARTE_INT_TXSTOPPED_MASK)) { + if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) && + nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_TXSTOPPED_MASK)) { txstopped_isr(dev); } } @@ -1739,6 +1754,7 @@ static const struct uart_driver_api uart_nrfx_uarte_driver_api = { #endif /* UARTE_INTERRUPT_DRIVEN */ }; +#ifdef UARTE_ENHANCED_POLL_OUT static int endtx_stoptx_ppi_init(NRF_UARTE_Type *uarte, struct uarte_nrfx_data *data) { @@ -1757,6 +1773,7 @@ static int endtx_stoptx_ppi_init(NRF_UARTE_Type *uarte, return 0; } +#endif /* UARTE_ENHANCED_POLL_OUT */ static int uarte_instance_init(const struct device *dev, uint8_t interrupts_active) @@ -1790,14 +1807,16 @@ static int uarte_instance_init(const struct device *dev, nrf_uarte_configure(uarte, &cfg->hw_config); #endif - if (IS_ENABLED(UARTE_ENHANCED_POLL_OUT) && - cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX) { +#ifdef UARTE_HAS_ENDTX_STOPTX_SHORT + nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_ENDTX_STOPTX); +#elif defined(UARTE_ENHANCED_POLL_OUT) + if (cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX) { err = endtx_stoptx_ppi_init(uarte, data); if (err < 0) { return err; } } - +#endif #ifdef UARTE_ANY_ASYNC if (data->async) { @@ -1819,7 +1838,7 @@ static int uarte_instance_init(const struct device *dev, } } - if (!(cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX)) { + if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) && !(cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX)) { nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK); } @@ -1850,7 +1869,8 @@ static int uarte_instance_init(const struct device *dev, static void wait_for_tx_stopped(const struct device *dev) { const struct uarte_nrfx_config *config = dev->config; - bool ppi_endtx = config->flags & UARTE_CFG_FLAG_PPI_ENDTX; + bool ppi_endtx = (config->flags & UARTE_CFG_FLAG_PPI_ENDTX) || + IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT); NRF_UARTE_Type *uarte = get_uarte_instance(dev); bool res; @@ -1982,10 +2002,6 @@ static int uarte_nrfx_pm_action(const struct device *dev, } #endif /* CONFIG_PM_DEVICE */ -#define UARTE(idx) DT_NODELABEL(uart##idx) -#define UARTE_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(UARTE(idx), prop) -#define UARTE_PROP(idx, prop) DT_PROP(UARTE(idx), prop) - #define UARTE_IRQ_CONFIGURE(idx, isr_handler) \ do { \ IRQ_CONNECT(DT_IRQN(UARTE(idx)), DT_IRQ(UARTE(idx), priority), \