From dbcbd87d3313d6a08f7bd70edf1f6a5058416870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Tue, 17 Sep 2024 14:15:04 +0200 Subject: [PATCH] [nrf fromlist] drivers: serial: nrfx_uarte: Add workaround for BAUDRATE register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On uart120 BAUDRATE register is not retained when ENABLE=0 and because of that BAUDRATE must be set after enabling. Add workaround to the driver. Upstream PR: https://github.com/zephyrproject-rtos/zephyr/pull/75462 Signed-off-by: Krzysztof Chruściński --- drivers/serial/uart_nrfx_uarte.c | 39 ++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 5da9c6b2702..150bd83725b 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -103,6 +103,16 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, 0); #define UARTE_ANY_CACHE 1 #endif +#ifdef UARTE_ANY_CACHE +/* uart120 instance does not retain BAUDRATE register when ENABLE=0. When this instance + * is used then baudrate must be set after enabling the peripheral and not before. + * This approach works for all instances so can be generally applied when uart120 is used. + * It is not default for all because it costs some resources. Since currently only uart120 + * needs cache, that is used to determine if workaround shall be applied. + */ +#define UARTE_BAUDRATE_RETENTION_WORKAROUND 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. @@ -187,6 +197,9 @@ struct uarte_nrfx_int_driven { struct uarte_nrfx_data { #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE struct uart_config uart_config; +#ifdef UARTE_BAUDRATE_RETENTION_WORKAROUND + nrf_uarte_baudrate_t nrf_baudrate; +#endif #endif #ifdef UARTE_INTERRUPT_DRIVEN struct uarte_nrfx_int_driven *int_driven; @@ -387,7 +400,6 @@ static int baudrate_set(const struct device *dev, uint32_t baudrate) const struct uarte_nrfx_config *config = dev->config; /* calculated baudrate divisor */ nrf_uarte_baudrate_t nrf_baudrate = NRF_BAUDRATE(baudrate); - NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (nrf_baudrate == 0) { return -EINVAL; @@ -398,7 +410,15 @@ static int baudrate_set(const struct device *dev, uint32_t baudrate) nrf_baudrate /= config->clock_freq / NRF_UARTE_BASE_FREQUENCY_16MHZ; } +#ifdef UARTE_BAUDRATE_RETENTION_WORKAROUND + struct uarte_nrfx_data *data = dev->data; + + data->nrf_baudrate = nrf_baudrate; +#else + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + nrf_uarte_baudrate_set(uarte, nrf_baudrate); +#endif return 0; } @@ -582,6 +602,13 @@ static void uarte_enable(const struct device *dev, uint32_t act_mask, uint32_t s } #endif nrf_uarte_enable(get_uarte_instance(dev)); +#if UARTE_BAUDRATE_RETENTION_WORKAROUND + nrf_uarte_baudrate_t baudrate = COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, + (data->nrf_baudrate), + (((const struct uarte_nrfx_config *)dev->config)->nrf_baudrate)); + + nrf_uarte_baudrate_set(get_uarte_instance(dev), baudrate); +#endif } /* At this point we should have irq locked and any previous transfer completed. @@ -2140,12 +2167,19 @@ static int uarte_nrfx_pm_action(const struct device *dev, switch (action) { case PM_DEVICE_ACTION_RESUME: - ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + { + ret = pins_state_change(dev, true); if (ret < 0) { return ret; } nrf_uarte_enable(uarte); +#if UARTE_BAUDRATE_RETENTION_WORKAROUND + nrf_uarte_baudrate_t baudrate = COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, + (data->nrf_baudrate), (cfg->nrf_baudrate)); + + nrf_uarte_baudrate_set(get_uarte_instance(dev), baudrate); +#endif #ifdef UARTE_ANY_ASYNC if (data->async) { @@ -2169,6 +2203,7 @@ static int uarte_nrfx_pm_action(const struct device *dev, #endif } break; + } case PM_DEVICE_ACTION_SUSPEND: /* Disabling UART requires stopping RX, but stop RX event is * only sent after each RX if async UART API is used.