From b5e279674b8948be8a96ec7024391e46f833a5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Mon, 24 Nov 2025 09:33:05 +0100 Subject: [PATCH] [nrf fromlist] drivers: uart_nrfx_uarte: Fix runtime device PM for interrupt driven API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing getting/putting of the device when the RX interrupt is enabled/disabled. Also fix enabling and disabling of the TX interrupt so that the device is got/put only if the interrupt wasn't already enabled/disabled and device PM reference counting is done correctly. This fixes `console_getchar()` that would hang when used with `CONFIG_PM_DEVICE_RUNTIME=y`. Upstream PR #: 99888 Signed-off-by: Andrzej Głąbek --- drivers/serial/uart_nrfx_uarte.c | 38 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index ffb090ca16f1..a60a1ee97aa1 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -2832,27 +2832,35 @@ static void uarte_nrfx_irq_tx_enable(const struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = dev->data; + bool already_enabled; - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(dev); - } + pm_device_runtime_get(dev); unsigned int key = irq_lock(); - data->int_driven->disable_tx_irq = false; - data->int_driven->tx_irq_enabled = true; - nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); + already_enabled = data->int_driven->tx_irq_enabled; + if (!already_enabled) { + data->int_driven->disable_tx_irq = false; + data->int_driven->tx_irq_enabled = true; + nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); + } irq_unlock(key); + + if (already_enabled) { + pm_device_runtime_put(dev); + } } /** Interrupt driven transfer disabling function */ static void uarte_nrfx_irq_tx_disable(const struct device *dev) { struct uarte_nrfx_data *data = dev->data; - /* TX IRQ will be disabled after current transmission is finished */ - data->int_driven->disable_tx_irq = true; - data->int_driven->tx_irq_enabled = false; + if (data->int_driven->tx_irq_enabled) { + /* TX IRQ will be disabled after current transmission is finished */ + data->int_driven->disable_tx_irq = true; + data->int_driven->tx_irq_enabled = false; + } } /** Interrupt driven transfer ready function */ @@ -2888,7 +2896,11 @@ static void uarte_nrfx_irq_rx_enable(const struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); - nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDRX_MASK); + if (!nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDRX_MASK)) { + pm_device_runtime_get(dev); + + nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDRX_MASK); + } } /** Interrupt driven receiver disabling function */ @@ -2896,7 +2908,11 @@ static void uarte_nrfx_irq_rx_disable(const struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); - nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ENDRX_MASK); + if (nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDRX_MASK)) { + pm_device_runtime_put_async(dev, K_NO_WAIT); + + nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ENDRX_MASK); + } } /** Interrupt driven error enabling function */