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
|
def_bool y
|
||||||
depends on DT_HAS_NORDIC_NRF_RTC_ENABLED
|
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
|
# Internal flag which detects if PPI wrap feature is enabled for any instance
|
||||||
config COUNTER_RTC_WITH_PPI_WRAP
|
config COUNTER_RTC_WITH_PPI_WRAP
|
||||||
def_bool $(dt_nodelabel_bool_prop,rtc0,ppi-wrap) || \
|
def_bool $(dt_nodelabel_bool_prop,rtc0,ppi-wrap) || \
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <zephyr/drivers/counter.h>
|
#include <zephyr/drivers/counter.h>
|
||||||
|
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
|
||||||
|
#include <zephyr/devicetree.h>
|
||||||
#include <hal/nrf_timer.h>
|
#include <hal/nrf_timer.h>
|
||||||
#include <zephyr/sys/atomic.h>
|
#include <zephyr/sys/atomic.h>
|
||||||
|
|
||||||
|
|
@ -32,11 +34,32 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL);
|
||||||
#define MAYBE_CONST_CONFIG const
|
#define MAYBE_CONST_CONFIG const
|
||||||
#endif
|
#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 {
|
struct counter_nrfx_data {
|
||||||
counter_top_callback_t top_cb;
|
counter_top_callback_t top_cb;
|
||||||
void *top_user_data;
|
void *top_user_data;
|
||||||
uint32_t guard_period;
|
uint32_t guard_period;
|
||||||
atomic_t cc_int_pending;
|
atomic_t cc_int_pending;
|
||||||
|
#ifdef COUNTER_ANY_FAST
|
||||||
|
atomic_t active;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct counter_nrfx_ch_data {
|
struct counter_nrfx_ch_data {
|
||||||
|
|
@ -48,6 +71,10 @@ struct counter_nrfx_config {
|
||||||
struct counter_config_info info;
|
struct counter_config_info info;
|
||||||
struct counter_nrfx_ch_data *ch_data;
|
struct counter_nrfx_ch_data *ch_data;
|
||||||
NRF_TIMER_Type *timer;
|
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);
|
LOG_INSTANCE_PTR_DECLARE(log);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -61,6 +88,18 @@ static int start(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct counter_nrfx_config *config = dev->config;
|
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);
|
nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_START);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -71,6 +110,18 @@ static int stop(const struct device *dev)
|
||||||
const struct counter_nrfx_config *config = dev->config;
|
const struct counter_nrfx_config *config = dev->config;
|
||||||
|
|
||||||
nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_STOP);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -403,6 +454,20 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = {
|
||||||
.set_guard_period = set_guard_period,
|
.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
|
* Device instantiation is done with node labels due to HAL API
|
||||||
* requirements. In particular, TIMERx_MAX_SIZE values from HALs
|
* 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)) \
|
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) \
|
#define COUNTER_NRFX_TIMER_DEVICE(idx) \
|
||||||
BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= \
|
BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= \
|
||||||
TIMER_PRESCALER_PRESCALER_Msk, \
|
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 = { \
|
static MAYBE_CONST_CONFIG struct counter_nrfx_config nrfx_counter_##idx##_config = { \
|
||||||
.info = { \
|
.info = { \
|
||||||
.max_top_value = (uint32_t)BIT64_MASK(DT_INST_PROP(idx, max_bit_width)),\
|
.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)), \
|
BIT(DT_INST_PROP(idx, prescaler)), \
|
||||||
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
|
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
|
||||||
.channels = CC_TO_ID(DT_INST_PROP(idx, cc_num)), \
|
.channels = CC_TO_ID(DT_INST_PROP(idx, cc_num)), \
|
||||||
}, \
|
}, \
|
||||||
.ch_data = counter##idx##_ch_data, \
|
.ch_data = counter##idx##_ch_data, \
|
||||||
.timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \
|
.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) \
|
LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \
|
||||||
}; \
|
}; \
|
||||||
CHECK_MAX_FREQ(idx); \
|
|
||||||
DEVICE_DT_INST_DEFINE(idx, \
|
DEVICE_DT_INST_DEFINE(idx, \
|
||||||
counter_##idx##_init, \
|
counter_##idx##_init, \
|
||||||
NULL, \
|
NULL, \
|
||||||
&counter_##idx##_data, \
|
&counter_##idx##_data, \
|
||||||
&nrfx_counter_##idx##_config.info, \
|
&nrfx_counter_##idx##_config.info, \
|
||||||
PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \
|
TIMER_INIT_LEVEL(idx), TIMER_INIT_PRIO(idx), \
|
||||||
&counter_nrfx_driver_api);
|
&counter_nrfx_driver_api);
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(COUNTER_NRFX_TIMER_DEVICE)
|
DT_INST_FOREACH_STATUS_OKAY(COUNTER_NRFX_TIMER_DEVICE)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue