drivers: counter: nrfx_timer: Add request for global HFSLL
Add requesting for global HFSLL when fast instance TIMER (e.g. TIMER120 in nrf54h20) is used. Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
fd194c1a01
commit
573ed56be7
2 changed files with 81 additions and 11 deletions
|
|
@ -9,6 +9,12 @@ config COUNTER_NRF_RTC
|
|||
def_bool y
|
||||
depends on DT_HAS_NORDIC_NRF_RTC_ENABLED
|
||||
|
||||
config COUNTER_NRFX_TIMER_USE_CLOCK_CONTROL
|
||||
def_bool y
|
||||
depends on $(dt_nodelabel_enabled,timer120) || \
|
||||
$(dt_nodelabel_enabled,timer121)
|
||||
select CLOCK_CONTROL
|
||||
|
||||
# Internal flag which detects if PPI wrap feature is enabled for any instance
|
||||
config COUNTER_RTC_WITH_PPI_WRAP
|
||||
def_bool $(dt_nodelabel_bool_prop,rtc0,ppi-wrap) || \
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <zephyr/drivers/counter.h>
|
||||
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <hal/nrf_timer.h>
|
||||
#include <zephyr/sys/atomic.h>
|
||||
|
||||
|
|
@ -32,11 +34,32 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL);
|
|||
#define MAYBE_CONST_CONFIG const
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_NRF54H20_GPD
|
||||
#include <nrf/gpd.h>
|
||||
|
||||
#define NRF_CLOCKS_INSTANCE_IS_FAST(node) \
|
||||
COND_CODE_1(DT_NODE_HAS_PROP(node, power_domains), \
|
||||
(IS_EQ(DT_PHA(node, power_domains, id), NRF_GPD_FAST_ACTIVE1)), \
|
||||
(0))
|
||||
|
||||
/* Macro must resolve to literal 0 or 1 */
|
||||
#define INSTANCE_IS_FAST(idx) NRF_CLOCKS_INSTANCE_IS_FAST(DT_DRV_INST(idx))
|
||||
|
||||
#define INSTANCE_IS_FAST_OR(idx) INSTANCE_IS_FAST(idx) ||
|
||||
|
||||
#if (DT_INST_FOREACH_STATUS_OKAY(INSTANCE_IS_FAST_OR) 0)
|
||||
#define COUNTER_ANY_FAST 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct counter_nrfx_data {
|
||||
counter_top_callback_t top_cb;
|
||||
void *top_user_data;
|
||||
uint32_t guard_period;
|
||||
atomic_t cc_int_pending;
|
||||
#ifdef COUNTER_ANY_FAST
|
||||
atomic_t active;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct counter_nrfx_ch_data {
|
||||
|
|
@ -48,6 +71,10 @@ struct counter_nrfx_config {
|
|||
struct counter_config_info info;
|
||||
struct counter_nrfx_ch_data *ch_data;
|
||||
NRF_TIMER_Type *timer;
|
||||
#ifdef COUNTER_ANY_FAST
|
||||
const struct device *clk_dev;
|
||||
struct nrf_clock_spec clk_spec;
|
||||
#endif
|
||||
LOG_INSTANCE_PTR_DECLARE(log);
|
||||
};
|
||||
|
||||
|
|
@ -61,6 +88,18 @@ static int start(const struct device *dev)
|
|||
{
|
||||
const struct counter_nrfx_config *config = dev->config;
|
||||
|
||||
#ifdef COUNTER_ANY_FAST
|
||||
struct counter_nrfx_data *data = dev->data;
|
||||
|
||||
if (config->clk_dev && atomic_cas(&data->active, 0, 1)) {
|
||||
int err;
|
||||
|
||||
err = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec, K_FOREVER);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_START);
|
||||
|
||||
return 0;
|
||||
|
|
@ -71,6 +110,18 @@ static int stop(const struct device *dev)
|
|||
const struct counter_nrfx_config *config = dev->config;
|
||||
|
||||
nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_STOP);
|
||||
#ifdef COUNTER_ANY_FAST
|
||||
struct counter_nrfx_data *data = dev->data;
|
||||
|
||||
if (config->clk_dev && atomic_cas(&data->active, 1, 0)) {
|
||||
int err;
|
||||
|
||||
err = nrf_clock_control_release(config->clk_dev, &config->clk_spec);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -403,6 +454,20 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = {
|
|||
.set_guard_period = set_guard_period,
|
||||
};
|
||||
|
||||
/* Get initialization level of an instance. Instances that requires clock control
|
||||
* which is using nrfs (IPC) are initialized later.
|
||||
*/
|
||||
#define TIMER_INIT_LEVEL(idx) \
|
||||
COND_CODE_1(INSTANCE_IS_FAST(idx), (POST_KERNEL), (PRE_KERNEL_1))
|
||||
|
||||
/* Get initialization priority of an instance. Instances that requires clock control
|
||||
* which is using nrfs (IPC) are initialized later.
|
||||
*/
|
||||
#define TIMER_INIT_PRIO(idx) \
|
||||
COND_CODE_1(INSTANCE_IS_FAST(idx), \
|
||||
(UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \
|
||||
(CONFIG_COUNTER_INIT_PRIORITY))
|
||||
|
||||
/*
|
||||
* Device instantiation is done with node labels due to HAL API
|
||||
* requirements. In particular, TIMERx_MAX_SIZE values from HALs
|
||||
|
|
@ -419,14 +484,6 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = {
|
|||
irq_handler, DEVICE_DT_INST_GET(idx), 0)) \
|
||||
)
|
||||
|
||||
#if !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
|
||||
#define CHECK_MAX_FREQ(idx) \
|
||||
BUILD_ASSERT(DT_INST_PROP(idx, max_frequency) == \
|
||||
NRF_TIMER_BASE_FREQUENCY_GET((NRF_TIMER_Type *)DT_INST_REG_ADDR(idx)))
|
||||
#else
|
||||
#define CHECK_MAX_FREQ(idx)
|
||||
#endif
|
||||
|
||||
#define COUNTER_NRFX_TIMER_DEVICE(idx) \
|
||||
BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= \
|
||||
TIMER_PRESCALER_PRESCALER_Msk, \
|
||||
|
|
@ -456,22 +513,29 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = {
|
|||
static MAYBE_CONST_CONFIG struct counter_nrfx_config nrfx_counter_##idx##_config = { \
|
||||
.info = { \
|
||||
.max_top_value = (uint32_t)BIT64_MASK(DT_INST_PROP(idx, max_bit_width)),\
|
||||
.freq = DT_INST_PROP(idx, max_frequency) / \
|
||||
.freq = NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(idx)) / \
|
||||
BIT(DT_INST_PROP(idx, prescaler)), \
|
||||
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
|
||||
.channels = CC_TO_ID(DT_INST_PROP(idx, cc_num)), \
|
||||
}, \
|
||||
.ch_data = counter##idx##_ch_data, \
|
||||
.timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \
|
||||
IF_ENABLED(INSTANCE_IS_FAST(idx), \
|
||||
(.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_DRV_INST(idx))), \
|
||||
.clk_spec = { \
|
||||
.frequency = NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(idx)), \
|
||||
.accuracy = 0, \
|
||||
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT, \
|
||||
}, \
|
||||
)) \
|
||||
LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \
|
||||
}; \
|
||||
CHECK_MAX_FREQ(idx); \
|
||||
DEVICE_DT_INST_DEFINE(idx, \
|
||||
counter_##idx##_init, \
|
||||
NULL, \
|
||||
&counter_##idx##_data, \
|
||||
&nrfx_counter_##idx##_config.info, \
|
||||
PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \
|
||||
TIMER_INIT_LEVEL(idx), TIMER_INIT_PRIO(idx), \
|
||||
&counter_nrfx_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(COUNTER_NRFX_TIMER_DEVICE)
|
||||
|
|
|
|||
Loading…
Reference in a new issue