Skip to content

Commit 15dabaa

Browse files
ananglfabiobaltieri
authored andcommitted
drivers: uart_nrfx_uarte: Fix runtime device PM for interrupt driven API
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`. Signed-off-by: Andrzej Głąbek <[email protected]>
1 parent 1feafdb commit 15dabaa

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

drivers/serial/uart_nrfx_uarte.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,27 +2832,35 @@ static void uarte_nrfx_irq_tx_enable(const struct device *dev)
28322832
{
28332833
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
28342834
struct uarte_nrfx_data *data = dev->data;
2835+
bool already_enabled;
28352836

2836-
if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
2837-
pm_device_runtime_get(dev);
2838-
}
2837+
pm_device_runtime_get(dev);
28392838

28402839
unsigned int key = irq_lock();
28412840

2842-
data->int_driven->disable_tx_irq = false;
2843-
data->int_driven->tx_irq_enabled = true;
2844-
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK);
2841+
already_enabled = data->int_driven->tx_irq_enabled;
2842+
if (!already_enabled) {
2843+
data->int_driven->disable_tx_irq = false;
2844+
data->int_driven->tx_irq_enabled = true;
2845+
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK);
2846+
}
28452847

28462848
irq_unlock(key);
2849+
2850+
if (already_enabled) {
2851+
pm_device_runtime_put(dev);
2852+
}
28472853
}
28482854

28492855
/** Interrupt driven transfer disabling function */
28502856
static void uarte_nrfx_irq_tx_disable(const struct device *dev)
28512857
{
28522858
struct uarte_nrfx_data *data = dev->data;
2853-
/* TX IRQ will be disabled after current transmission is finished */
2854-
data->int_driven->disable_tx_irq = true;
2855-
data->int_driven->tx_irq_enabled = false;
2859+
if (data->int_driven->tx_irq_enabled) {
2860+
/* TX IRQ will be disabled after current transmission is finished */
2861+
data->int_driven->disable_tx_irq = true;
2862+
data->int_driven->tx_irq_enabled = false;
2863+
}
28562864
}
28572865

28582866
/** Interrupt driven transfer ready function */
@@ -2888,15 +2896,23 @@ static void uarte_nrfx_irq_rx_enable(const struct device *dev)
28882896
{
28892897
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
28902898

2891-
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDRX_MASK);
2899+
if (!nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDRX_MASK)) {
2900+
pm_device_runtime_get(dev);
2901+
2902+
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDRX_MASK);
2903+
}
28922904
}
28932905

28942906
/** Interrupt driven receiver disabling function */
28952907
static void uarte_nrfx_irq_rx_disable(const struct device *dev)
28962908
{
28972909
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
28982910

2899-
nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ENDRX_MASK);
2911+
if (nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDRX_MASK)) {
2912+
pm_device_runtime_put_async(dev, K_NO_WAIT);
2913+
2914+
nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ENDRX_MASK);
2915+
}
29002916
}
29012917

29022918
/** Interrupt driven error enabling function */

0 commit comments

Comments
 (0)