Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions drivers/counter/Kconfig.nrfx
Original file line number Diff line number Diff line change
Expand Up @@ -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) || \
Expand Down
86 changes: 75 additions & 11 deletions drivers/counter/counter_nrfx_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -32,11 +34,32 @@
#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))

Check notice on line 44 in drivers/counter/counter_nrfx_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/counter/counter_nrfx_timer.c:44 -#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)) +#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 {
Expand All @@ -48,6 +71,10 @@
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);
};

Expand All @@ -61,6 +88,18 @@
{
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;
Expand All @@ -71,6 +110,18 @@
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;
}
Expand Down Expand Up @@ -403,6 +454,20 @@
.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))

Check notice on line 469 in drivers/counter/counter_nrfx_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/counter/counter_nrfx_timer.c:469 -#define TIMER_INIT_LEVEL(idx) \ - COND_CODE_1(INSTANCE_IS_FAST(idx), (POST_KERNEL), (PRE_KERNEL_1)) +#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)), \ +#define TIMER_INIT_PRIO(idx) \ + COND_CODE_1(INSTANCE_IS_FAST(idx), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \

/*
* Device instantiation is done with node labels due to HAL API
* requirements. In particular, TIMERx_MAX_SIZE values from HALs
Expand All @@ -419,14 +484,6 @@
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, \
Expand Down Expand Up @@ -456,22 +513,29 @@
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);

Check notice on line 540 in drivers/counter/counter_nrfx_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/counter/counter_nrfx_timer.c:540 -#define COUNTER_NRFX_TIMER_DEVICE(idx) \ - BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= \ - TIMER_PRESCALER_PRESCALER_Msk, \ - "TIMER prescaler out of range"); \ - COND_CODE_1(DT_INST_PROP(idx, zli), ( \ - ISR_DIRECT_DECLARE(counter_timer##idx##_isr_wrapper) \ - { \ - irq_handler(DEVICE_DT_INST_GET(idx)); \ - /* No rescheduling, it shall not access zephyr primitives. */ \ - return 0; \ - }), ()) \ - static int counter_##idx##_init(const struct device *dev) \ - { \ - TIMER_IRQ_CONNECT(idx); \ - static const struct counter_timer_config config = { \ - .prescaler = DT_INST_PROP(idx, prescaler), \ - .mode = NRF_TIMER_MODE_TIMER, \ - .bit_width = (DT_INST_PROP(idx, max_bit_width) == 32) ? \ - NRF_TIMER_BIT_WIDTH_32 : NRF_TIMER_BIT_WIDTH_16, \ - }; \ - return init_timer(dev, &config); \ - } \ - static struct counter_nrfx_data counter_##idx##_data; \ - static struct counter_nrfx_ch_data \ - counter##idx##_ch_data[CC_TO_ID(DT_INST_PROP(idx, cc_num))]; \ - LOG_INSTANCE_REGISTER(LOG_MODULE_NAME, idx, CONFIG_COUNTER_LOG_LEVEL); \ - 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 = 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) \ - }; \ - DEVICE_DT_INST_DEFINE(idx, \ - counter_##idx##_init, \ - NULL, \ - &counter_##idx##_data, \ - &nrfx_counter_##idx##_config.info, \ - TIMER_INIT_LEVEL(idx), TIMER_INIT_PRIO(idx), \ - &counter_nrfx_driver_api); +#define COUNTER_NRFX_TIMER_DEVICE(idx) \ + BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= TIMER_PRESCALER_PRESCALER_Msk, \ + "TIMER prescaler out of range"); \ + COND_CODE_1(DT_INST_PROP(idx, zli), \ + (ISR_DIRECT_DECLARE(counter_timer##idx##_isr_wrapper) { \ + irq_handler(DEVICE_DT_INST_GET(idx)); \ + /* No rescheduling, it shall not access zephyr primitives. */ \ + return 0; \ + }), \ + ()) \ + static int counter_##idx##_init(const struct device *dev) \ + { \ + TIMER_IRQ_CONNECT(idx); \ + static const struct counter_timer_config config = { \ + .prescaler = DT_INST_PROP(idx, prescaler), \ + .mode = NRF_TIMER_MODE_TIMER, \ + .bit_width = (DT_INST_PROP(idx, max_bit_width) == 32) \ + ? NRF_TIMER_BIT_WIDTH_32 \ + : NRF_TIMER_BIT_WIDTH_16, \ + };
DT_INST_FOREACH_STATUS_OKAY(COUNTER_NRFX_TIMER_DEVICE)
2 changes: 2 additions & 0 deletions dts/common/nordic/nrf54h20.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@
power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>;
max-bit-width = <32>;
max-frequency = <DT_FREQ_M(320)>;
clocks = <&hsfll120>;
prescaler = <0>;
};

Expand All @@ -635,6 +636,7 @@
power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>;
max-bit-width = <32>;
max-frequency = <DT_FREQ_M(320)>;
clocks = <&hsfll120>;
prescaler = <0>;
};

Expand Down
12 changes: 12 additions & 0 deletions modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,19 @@
}
}

/* Update MDK variable which is used by nrfx_coredep_delay_us (k_busy_wait). */
static void dvfs_service_update_core_clock(enum dvfs_frequency_setting oppoint_freq)
{
extern uint32_t SystemCoreClock;

SystemCoreClock = oppoint_freq == DVFS_FREQ_HIGH ? 320000000 :
oppoint_freq == DVFS_FREQ_MEDLOW ? 128000000 : 64000000;
}

Check notice on line 149 in modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c:149 - SystemCoreClock = oppoint_freq == DVFS_FREQ_HIGH ? 320000000 : - oppoint_freq == DVFS_FREQ_MEDLOW ? 128000000 : 64000000; + SystemCoreClock = oppoint_freq == DVFS_FREQ_HIGH ? 320000000 + : oppoint_freq == DVFS_FREQ_MEDLOW ? 128000000 + : 64000000;

/* Perform scaling finnish procedure. */
static void dvfs_service_handler_scaling_finish(enum dvfs_frequency_setting oppoint_freq)
{

LOG_DBG("Scaling finnish oppoint freq %d", oppoint_freq);
ld_dvfs_scaling_finish(dvfs_service_handler_is_downscaling(oppoint_freq));
if (!dvfs_service_handler_is_downscaling(oppoint_freq)) {
Expand All @@ -153,6 +163,7 @@
}
dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_REQ_PENDING_BIT_POS);
current_freq_setting = oppoint_freq;
dvfs_service_update_core_clock(oppoint_freq);
LOG_DBG("Current LD freq setting: %d", current_freq_setting);
if (dvfs_frequency_change_applied_clb) {
dvfs_frequency_change_applied_clb(current_freq_setting);
Expand Down Expand Up @@ -216,6 +227,7 @@
dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_REQ_PENDING_BIT_POS);
LOG_DBG("DVFS handler EVT_OPPOINT_REQ_CONFIRMED %d", (uint32_t)p_evt->freq);
if (dvfs_service_handler_get_requested_oppoint() == p_evt->freq) {
dvfs_service_update_core_clock(p_evt->freq);
if (dvfs_frequency_change_applied_clb) {
dvfs_frequency_change_applied_clb(p_evt->freq);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
zephyr,pm-device-runtime-auto;
dut_spi_dt: test-spi-dev@0 {
compatible = "vnd,spi-device";
spi-max-frequency = <DT_FREQ_M(8)>;
reg = <0>;
};
};
Expand Down
Loading