Skip to content

Commit e231189

Browse files
committed
[nrf fromtree] drivers: serial: nrfx_uarte: Add support for higher baudrates
nrf54x devices have UARTE instance capable of using baudrate higher than 1M. Higher baudrates does not have predefined values for BAUDRATE register. A formula can be used to calculate BAUDRATE value that shall be used for desired baudrate. Add UARTE_ANY_HIGH_SPEED macro which is set when high speed is enabled (uart00 in nrf54lx or uart120 in nrf54h20). For high speed instance use formula for getting value that shall be written to BAUDRATE register. When runtime configuration is not used then same formula is used to calculate fixed BAUDRATE value. Signed-off-by: Krzysztof Chruściński <[email protected]> (cherry picked from commit 972ec82)
1 parent bcf7776 commit e231189

File tree

1 file changed

+41
-16
lines changed

1 file changed

+41
-16
lines changed

drivers/serial/uart_nrfx_uarte.c

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME));
126126
#endif
127127
#endif
128128

129+
#define INSTANCE_IS_HIGH_SPEED(unused, prefix, idx, _) \
130+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(prefix##idx)), \
131+
((NRF_PERIPH_GET_FREQUENCY(UARTE(prefix##idx)) > NRF_UARTE_BASE_FREQUENCY_16MHZ)), \
132+
(0))
133+
134+
/* Macro determines if there is any high speed instance (instance that is driven using
135+
* clock that is faster than 16 MHz).
136+
*/
137+
#define UARTE_ANY_HIGH_SPEED (UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_HIGH_SPEED, (||), (0)))
138+
129139
#ifdef UARTE_ANY_CACHE
130140
/* uart120 instance does not retain BAUDRATE register when ENABLE=0. When this instance
131141
* is used then baudrate must be set after enabling the peripheral and not before.
@@ -256,6 +266,17 @@ struct uarte_nrfx_data {
256266
/* If enabled then UARTE peripheral is using memory which is cacheable. */
257267
#define UARTE_CFG_FLAG_CACHEABLE BIT(3)
258268

269+
/* Formula for getting the baudrate settings is following:
270+
* 2^12 * (2^20 / (f_PCLK / desired_baudrate)) where f_PCLK is a frequency that
271+
* drives the UARTE.
272+
*
273+
* @param f_pclk Frequency of the clock that drives the peripheral.
274+
* @param baudrate Desired baudrate.
275+
*
276+
* @return Baudrate setting to be written to the BAUDRATE register
277+
*/
278+
#define UARTE_GET_CUSTOM_BAUDRATE(f_pclk, baudrate) ((BIT(20) / (f_pclk / baudrate)) << 12)
279+
259280
/* Macro for converting numerical baudrate to register value. It is convenient
260281
* to use this approach because for constant input it can calculate nrf setting
261282
* at compile time.
@@ -495,18 +516,19 @@ static void uarte_nrfx_isr_int(const void *arg)
495516
static int baudrate_set(const struct device *dev, uint32_t baudrate)
496517
{
497518
const struct uarte_nrfx_config *config = dev->config;
519+
nrf_uarte_baudrate_t nrf_baudrate;
520+
498521
/* calculated baudrate divisor */
499-
nrf_uarte_baudrate_t nrf_baudrate = NRF_BAUDRATE(baudrate);
522+
if (UARTE_ANY_HIGH_SPEED && (config->clock_freq > NRF_UARTE_BASE_FREQUENCY_16MHZ)) {
523+
nrf_baudrate = UARTE_GET_CUSTOM_BAUDRATE(config->clock_freq, baudrate);
524+
} else {
525+
nrf_baudrate = NRF_BAUDRATE(baudrate);
526+
}
500527

501528
if (nrf_baudrate == 0) {
502529
return -EINVAL;
503530
}
504531

505-
/* scale baudrate setting */
506-
if (config->clock_freq > 0U) {
507-
nrf_baudrate /= config->clock_freq / NRF_UARTE_BASE_FREQUENCY_16MHZ;
508-
}
509-
510532
#ifdef UARTE_BAUDRATE_RETENTION_WORKAROUND
511533
struct uarte_nrfx_data *data = dev->data;
512534

@@ -2413,17 +2435,21 @@ static int uarte_instance_init(const struct device *dev,
24132435
#define UARTE_DISABLE_RX_INIT(node_id) \
24142436
.disable_rx = DT_PROP(node_id, disable_rx)
24152437

2416-
/* Get frequency of the clock that driver the UARTE peripheral. Clock node can
2417-
* have fixed or variable frequency. For fast UARTE use highest supported frequency.
2418-
*/
2419-
#define UARTE_GET_BAUDRATE_DIV(idx) \
2420-
(NRF_PERIPH_GET_FREQUENCY(UARTE(idx)) / NRF_UARTE_BASE_FREQUENCY_16MHZ)
2438+
/* Get frequency divider that is used to adjust the BAUDRATE value. */
2439+
#define UARTE_GET_BAUDRATE_DIV(f_pclk) (f_pclk / NRF_UARTE_BASE_FREQUENCY_16MHZ)
24212440

24222441
/* When calculating baudrate we need to take into account that high speed instances
24232442
* must have baudrate adjust to the ratio between UARTE clocking frequency and 16 MHz.
2443+
* Additionally, >1Mbaud speeds are calculated using a formula.
24242444
*/
2445+
#define UARTE_GET_BAUDRATE2(f_pclk, current_speed) \
2446+
((f_pclk > NRF_UARTE_BASE_FREQUENCY_16MHZ) && (current_speed > 1000000)) ? \
2447+
UARTE_GET_CUSTOM_BAUDRATE(f_pclk, current_speed) : \
2448+
(NRF_BAUDRATE(current_speed) / UARTE_GET_BAUDRATE_DIV(f_pclk))
2449+
2450+
/* Convert DT current-speed to a value that is written to the BAUDRATE register. */
24252451
#define UARTE_GET_BAUDRATE(idx) \
2426-
(NRF_BAUDRATE(UARTE_PROP(idx, current_speed)) / UARTE_GET_BAUDRATE_DIV(idx))
2452+
UARTE_GET_BAUDRATE2(NRF_PERIPH_GET_FREQUENCY(UARTE(idx)), UARTE_PROP(idx, current_speed))
24272453

24282454
/* Get initialization level of an instance. Instances that requires clock control
24292455
* which is using nrfs (IPC) are initialized later.
@@ -2488,12 +2514,11 @@ static int uarte_instance_init(const struct device *dev,
24882514
(.int_driven = &uarte##idx##_int_driven,)) \
24892515
}; \
24902516
COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, (), \
2491-
(BUILD_ASSERT(NRF_BAUDRATE(UARTE_PROP(idx, current_speed)) > 0,\
2492-
"Unsupported baudrate");)) \
2517+
(BUILD_ASSERT(UARTE_GET_BAUDRATE(idx) > 0, \
2518+
"Unsupported baudrate");)) \
24932519
static const struct uarte_nrfx_config uarte_##idx##z_config = { \
24942520
COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, \
2495-
(IF_ENABLED(DT_CLOCKS_HAS_IDX(UARTE(idx), 0), \
2496-
(.clock_freq = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),))), \
2521+
(.clock_freq = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),), \
24972522
(IF_ENABLED(UARTE_HAS_FRAME_TIMEOUT, \
24982523
(.baudrate = UARTE_PROP(idx, current_speed),)) \
24992524
.nrf_baudrate = UARTE_GET_BAUDRATE(idx), \

0 commit comments

Comments
 (0)