Skip to content

Commit 97550ee

Browse files
drivers: serial: nrfx_uarte: enable cross domain pins for nRF54L15
UARTE20 and UARTE21 instances enable usage of pins on different port, but require request for constant latency mode. Added handling of such scenario in the driver. Added testcase to cover it. Signed-off-by: Michał Stasiak <[email protected]>
1 parent d6abfeb commit 97550ee

File tree

5 files changed

+119
-0
lines changed

5 files changed

+119
-0
lines changed

drivers/serial/uart_nrfx_uarte.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,21 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME));
136136
*/
137137
#define UARTE_ANY_HIGH_SPEED (UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_HIGH_SPEED, (||), (0)))
138138

139+
#define UARTE_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \
140+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(prefix##idx)), \
141+
(UTIL_AND(UARTE_PROP(idx, cross_domain_constlat_required), \
142+
UARTE_HAS_PROP(idx, default_port))), \
143+
(0))
144+
145+
#if (UARTE_FOR_EACH_INSTANCE(UARTE_PINS_CROSS_DOMAIN, (||), (0))) && defined(CONFIG_NRFX_POWER)
146+
#include <hal/nrf_gpio.h>
147+
#include <nrfx_power.h>
148+
/* Macro determines if there is any UART instance that needs constant latency mode if using
149+
* cross domain pins. To use constant latency, NRFX_POWER needs to be enabled.
150+
*/
151+
#define UARTE_ANY_PINS_CROSS_DOMAIN 1
152+
#endif
153+
139154
#ifdef UARTE_ANY_CACHE
140155
/* uart120 instance does not retain BAUDRATE register when ENABLE=0. When this instance
141156
* is used then baudrate must be set after enabling the peripheral and not before.
@@ -357,6 +372,10 @@ struct uarte_nrfx_config {
357372
#endif
358373
uint8_t *poll_out_byte;
359374
uint8_t *poll_in_byte;
375+
#if UARTE_ANY_PINS_CROSS_DOMAIN
376+
bool cross_domain;
377+
uint8_t default_port;
378+
#endif
360379
};
361380

362381
/* Using Macro instead of static inline function to handle NO_OPTIMIZATIONS case
@@ -426,6 +445,31 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask)
426445
nrf_uarte_disable(get_uarte_instance(dev));
427446
}
428447

448+
#if UARTE_ANY_PINS_CROSS_DOMAIN
449+
static bool uarte_has_cross_domain_connection(const struct uarte_nrfx_config *config)
450+
{
451+
const struct pinctrl_dev_config *pcfg = config->pcfg;
452+
const struct pinctrl_state *state;
453+
int ret;
454+
455+
ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state);
456+
if (ret < 0) {
457+
LOG_ERR("Unable to read pin state");
458+
return false;
459+
}
460+
461+
for (uint8_t i = 0U; i < state->pin_cnt; i++) {
462+
uint32_t pin = NRF_GET_PIN(state->pins[i]);
463+
464+
if (nrf_gpio_pin_port_number_extract(&pin) != config->default_port) {
465+
return true;
466+
}
467+
}
468+
469+
return false;
470+
}
471+
#endif
472+
429473
#ifdef UARTE_ANY_NONE_ASYNC
430474
/**
431475
* @brief Interrupt service routine.
@@ -709,6 +753,15 @@ static void uarte_periph_enable(const struct device *dev)
709753
#ifdef CONFIG_SOC_NRF54H20_GPD
710754
nrf_gpd_retain_pins_set(config->pcfg, false);
711755
#endif
756+
#if UARTE_ANY_PINS_CROSS_DOMAIN
757+
if (config->cross_domain && uarte_has_cross_domain_connection(config)) {
758+
int err;
759+
760+
err = nrfx_power_constlat_mode_request();
761+
(void)err;
762+
__ASSERT_NO_MSG(err >= 0);
763+
}
764+
#endif
712765
#if UARTE_BAUDRATE_RETENTION_WORKAROUND
713766
nrf_uarte_baudrate_set(uarte,
714767
COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE,
@@ -2341,6 +2394,15 @@ static void uarte_pm_suspend(const struct device *dev)
23412394
#ifdef CONFIG_SOC_NRF54H20_GPD
23422395
nrf_gpd_retain_pins_set(cfg->pcfg, true);
23432396
#endif
2397+
#if UARTE_ANY_PINS_CROSS_DOMAIN
2398+
if (cfg->cross_domain && uarte_has_cross_domain_connection(cfg)) {
2399+
int err;
2400+
2401+
err = nrfx_power_constlat_mode_free();
2402+
(void)err;
2403+
__ASSERT_NO_MSG(err >= 0);
2404+
}
2405+
#endif
23442406

23452407
nrf_uarte_disable(uarte);
23462408

@@ -2601,6 +2663,11 @@ static int uarte_instance_init(const struct device *dev,
26012663
.accuracy = 0, \
26022664
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,\
26032665
},)) \
2666+
IF_ENABLED(UTIL_AND( \
2667+
UARTE_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \
2668+
CONFIG_NRFX_POWER), \
2669+
(.cross_domain = true, \
2670+
.default_port = UARTE_PROP(idx, default_port),)) \
26042671
}; \
26052672
static int uarte_##idx##_init(const struct device *dev) \
26062673
{ \

dts/bindings/serial/nordic,nrf-uarte.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,13 @@ properties:
1414
type: boolean
1515
description: |
1616
UARTE has RX frame timeout HW feature.
17+
18+
cross-domain-constlat-required:
19+
type: boolean
20+
description: |
21+
UARTE needs constant latency mode if using cross domain pins.
22+
23+
default-port:
24+
type: int
25+
description: |
26+
UARTE default GPIO port.

dts/common/nordic/nrf54l_05_10_15.dtsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,8 @@
320320
status = "disabled";
321321
endtx-stoptx-supported;
322322
frame-timeout-supported;
323+
cross-domain-constlat-required;
324+
default-port = <0x1>;
323325
};
324326

325327
i2c21: i2c@c7000 {
@@ -359,6 +361,8 @@
359361
status = "disabled";
360362
endtx-stoptx-supported;
361363
frame-timeout-supported;
364+
cross-domain-constlat-required;
365+
default-port = <0x1>;
362366
};
363367

364368
i2c22: i2c@c8000 {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* SPDX-License-Identifier: Apache-2.0 */
2+
3+
&pinctrl {
4+
uart21_default: uart21_default {
5+
group1 {
6+
psels = <NRF_PSEL(UART_TX, 2, 8)>,
7+
<NRF_PSEL(UART_RX, 2, 7)>,
8+
<NRF_PSEL(UART_RTS, 2, 10)>,
9+
<NRF_PSEL(UART_CTS, 2, 9)>;
10+
};
11+
};
12+
13+
uart21_sleep: uart21_sleep {
14+
group1 {
15+
psels = <NRF_PSEL(UART_TX, 2, 8)>,
16+
<NRF_PSEL(UART_RX, 2, 7)>,
17+
<NRF_PSEL(UART_RTS, 2, 10)>,
18+
<NRF_PSEL(UART_CTS, 2, 9)>;
19+
low-power-enable;
20+
};
21+
};
22+
};
23+
24+
dut: &uart21 {
25+
status = "okay";
26+
current-speed = <115200>;
27+
pinctrl-0 = <&uart21_default>;
28+
pinctrl-1 = <&uart21_sleep>;
29+
pinctrl-names = "default", "sleep";
30+
hw-flow-control;
31+
};

tests/drivers/uart/uart_elementary/testcase.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,10 @@ tests:
107107
extra_configs:
108108
- CONFIG_DUAL_UART_TEST=y
109109
- CONFIG_SETUP_MISMATCH_TEST=y
110+
drivers.uart.uart_elementary_cross_domain:
111+
filter: CONFIG_SERIAL_SUPPORT_INTERRUPT
112+
platform_allow:
113+
- nrf54l15dk/nrf54l15/cpuapp
114+
extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay"
115+
extra_configs:
116+
- CONFIG_NRFX_POWER=y

0 commit comments

Comments
 (0)