Skip to content

Commit e9f9cc6

Browse files
nordic-krchkartben
authored andcommitted
drivers: serial: nrfx_uarte: Request hsfll clock for fast instance
Request fast global domain to run at 320 MHz during fast UARTE activity. As request is asynchronous it cannot be called from an ISR. Due to complexity to handle that without device runtime power management a requirement is added so that if fast UARTE is used device runtime PM must be enabled. Clock is request and released in PM resume and suspended actions which in case of fast UARTE are only called from thread context. Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent 573ed56 commit e9f9cc6

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

drivers/serial/Kconfig.nrfx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ rsource "Kconfig.nrfx_uart_instance"
101101
endif
102102

103103
if HAS_HW_NRF_UARTE120
104+
105+
config UART_NRFX_UARTE_USE_CLOCK_CONTROL
106+
def_bool y
107+
select CLOCK_CONTROL
108+
104109
nrfx_uart_num = 120
105110
rsource "Kconfig.nrfx_uart_instance"
106111
endif

drivers/serial/uart_nrfx_uarte.c

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@
2323
#include <zephyr/linker/devicetree_regions.h>
2424
#include <zephyr/irq.h>
2525
#include <zephyr/logging/log.h>
26-
27-
#ifdef CONFIG_SOC_NRF54H20_GPD
28-
#include <nrf/gpd.h>
29-
#endif
26+
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
3027

3128
LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL);
3229

@@ -110,17 +107,22 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL);
110107
#define UARTE_ANY_LOW_POWER 1
111108
#endif
112109

110+
#ifdef CONFIG_SOC_NRF54H20_GPD
111+
#include <nrf/gpd.h>
112+
113113
/* Macro must resolve to literal 0 or 1 */
114-
#define INSTANCE_IS_FAST(unused, prefix, idx, _) \
115-
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(idx)), \
116-
(COND_CODE_1(UTIL_AND(IS_ENABLED(CONFIG_SOC_NRF54H20_GPD), \
117-
DT_NODE_HAS_PROP(UARTE(idx), power_domains)), \
118-
(COND_CODE_0(DT_PHA(UARTE(idx), power_domains, id), (1), (0))),\
119-
(0))), (0))
114+
#define INSTANCE_IS_FAST(unused, prefix, idx, _) \
115+
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(idx)), \
116+
(COND_CODE_1(DT_NODE_HAS_PROP(UARTE(idx), power_domains), \
117+
(IS_EQ(DT_PHA(UARTE(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \
118+
(0))), (0))
120119

121120
#if UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_FAST, (||), (0))
121+
/* Fast instance requires special PM treatment so device runtime PM must be enabled. */
122+
BUILD_ASSERT(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME));
122123
#define UARTE_ANY_FAST 1
123124
#endif
125+
#endif
124126

125127
#ifdef UARTE_ANY_CACHE
126128
/* uart120 instance does not retain BAUDRATE register when ENABLE=0. When this instance
@@ -307,6 +309,10 @@ struct uarte_nrfx_config {
307309
#ifdef CONFIG_HAS_NORDIC_DMM
308310
void *mem_reg;
309311
#endif
312+
#ifdef UARTE_ANY_FAST
313+
const struct device *clk_dev;
314+
struct nrf_clock_spec clk_spec;
315+
#endif
310316
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
311317
/* None-zero in case of high speed instances. Baudrate is adjusted by that ratio. */
312318
uint32_t clock_freq;
@@ -656,6 +662,16 @@ static void uarte_periph_enable(const struct device *dev)
656662
struct uarte_nrfx_data *data = dev->data;
657663

658664
(void)data;
665+
#ifdef UARTE_ANY_FAST
666+
if (config->clk_dev) {
667+
int err;
668+
669+
err = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec, K_FOREVER);
670+
(void)err;
671+
__ASSERT_NO_MSG(err >= 0);
672+
}
673+
#endif
674+
659675
nrf_uarte_enable(uarte);
660676
#ifdef CONFIG_SOC_NRF54H20_GPD
661677
nrf_gpd_retain_pins_set(config->pcfg, false);
@@ -737,7 +753,6 @@ static void tx_start(const struct device *dev, const uint8_t *buf, size_t len)
737753
if (LOW_POWER_ENABLED(config)) {
738754
uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_TX);
739755
}
740-
741756
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX);
742757
}
743758

@@ -2203,6 +2218,16 @@ static void uarte_pm_suspend(const struct device *dev)
22032218
struct uarte_nrfx_data *data = dev->data;
22042219

22052220
(void)data;
2221+
#ifdef UARTE_ANY_FAST
2222+
if (cfg->clk_dev) {
2223+
int err;
2224+
2225+
err = nrf_clock_control_release(cfg->clk_dev, &cfg->clk_spec);
2226+
(void)err;
2227+
__ASSERT_NO_MSG(err >= 0);
2228+
}
2229+
#endif
2230+
22062231
#ifdef UARTE_ANY_ASYNC
22072232
if (data->async) {
22082233
/* Entering inactive state requires device to be no
@@ -2386,18 +2411,31 @@ static int uarte_instance_init(const struct device *dev,
23862411
#define UARTE_DISABLE_RX_INIT(node_id) \
23872412
.disable_rx = DT_PROP(node_id, disable_rx)
23882413

2389-
#define UARTE_GET_FREQ(idx) DT_PROP(DT_CLOCKS_CTLR(UARTE(idx)), clock_frequency)
2390-
2391-
#define UARTE_GET_BAUDRATE_DIV(idx) \
2392-
COND_CODE_1(DT_CLOCKS_HAS_IDX(UARTE(idx), 0), \
2393-
((UARTE_GET_FREQ(idx) / NRF_UARTE_BASE_FREQUENCY_16MHZ)), (1))
2414+
/* Get frequency of the clock that driver the UARTE peripheral. Clock node can
2415+
* have fixed or variable frequency. For fast UARTE use highest supported frequency.
2416+
*/
2417+
#define UARTE_GET_BAUDRATE_DIV(idx) \
2418+
(NRF_PERIPH_GET_FREQUENCY(UARTE(idx)) / NRF_UARTE_BASE_FREQUENCY_16MHZ)
23942419

23952420
/* When calculating baudrate we need to take into account that high speed instances
23962421
* must have baudrate adjust to the ratio between UARTE clocking frequency and 16 MHz.
23972422
*/
23982423
#define UARTE_GET_BAUDRATE(idx) \
23992424
(NRF_BAUDRATE(UARTE_PROP(idx, current_speed)) / UARTE_GET_BAUDRATE_DIV(idx))
24002425

2426+
/* Get initialization level of an instance. Instances that requires clock control
2427+
* which is using nrfs (IPC) are initialized later.
2428+
*/
2429+
#define UARTE_INIT_LEVEL(idx) \
2430+
COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), (POST_KERNEL), (PRE_KERNEL_1))
2431+
2432+
/* Get initialization priority of an instance. Instances that requires clock control
2433+
* which is using nrfs (IPC) are initialized later.
2434+
*/
2435+
#define UARTE_INIT_PRIO(idx) \
2436+
COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \
2437+
(UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \
2438+
(CONFIG_SERIAL_INIT_PRIORITY))
24012439

24022440
/* Macro for setting nRF specific configuration structures. */
24032441
#define UARTE_NRF_CONFIG(idx) { \
@@ -2453,7 +2491,7 @@ static int uarte_instance_init(const struct device *dev,
24532491
static const struct uarte_nrfx_config uarte_##idx##z_config = { \
24542492
COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, \
24552493
(IF_ENABLED(DT_CLOCKS_HAS_IDX(UARTE(idx), 0), \
2456-
(.clock_freq = UARTE_GET_FREQ(idx),))), \
2494+
(.clock_freq = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),))), \
24572495
(IF_ENABLED(UARTE_HAS_FRAME_TIMEOUT, \
24582496
(.baudrate = UARTE_PROP(idx, current_speed),)) \
24592497
.nrf_baudrate = UARTE_GET_BAUDRATE(idx), \
@@ -2480,6 +2518,13 @@ static int uarte_instance_init(const struct device *dev,
24802518
IF_ENABLED(CONFIG_UART_##idx##_NRF_HW_ASYNC, \
24812519
(.timer = NRFX_TIMER_INSTANCE( \
24822520
CONFIG_UART_##idx##_NRF_HW_ASYNC_TIMER),)) \
2521+
IF_ENABLED(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \
2522+
(.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(UARTE(idx))), \
2523+
.clk_spec = { \
2524+
.frequency = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),\
2525+
.accuracy = 0, \
2526+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,\
2527+
},)) \
24832528
}; \
24842529
static int uarte_##idx##_init(const struct device *dev) \
24852530
{ \
@@ -2500,8 +2545,8 @@ static int uarte_instance_init(const struct device *dev,
25002545
PM_DEVICE_DT_GET(UARTE(idx)), \
25012546
&uarte_##idx##_data, \
25022547
&uarte_##idx##z_config, \
2503-
PRE_KERNEL_1, \
2504-
CONFIG_SERIAL_INIT_PRIORITY, \
2548+
UARTE_INIT_LEVEL(idx), \
2549+
UARTE_INIT_PRIO(idx), \
25052550
&uart_nrfx_uarte_driver_api)
25062551

25072552
#define UARTE_INT_DRIVEN(idx) \

0 commit comments

Comments
 (0)