From b1ced753867bdd41ea75c6883302a1fff2996236 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 4 Nov 2021 12:51:39 +0100 Subject: [PATCH] drivers: timer: move initialization setup to drivers The weak symbol sys_clock_driver_init has been removed, therefore moving the init responsability to the drivers themselves. As a result, the init function has now been made static on all drivers and moved to the bottom, following the convention used in other areas. Signed-off-by: Gerard Marull-Paretas --- boards/arm/qemu_cortex_m0/nrf_timer_timer.c | 53 ++-- drivers/timer/altera_avalon_timer_hal.c | 39 +-- drivers/timer/apic_timer.c | 6 +- drivers/timer/apic_tsc.c | 6 +- drivers/timer/arcv2_timer0.c | 92 +++---- drivers/timer/arm_arch_timer.c | 35 +-- drivers/timer/cavs_timer.c | 29 ++- drivers/timer/cc13x2_cc26x2_rtc_timer.c | 40 +-- drivers/timer/cortex_m_systick.c | 34 +-- drivers/timer/esp32c3_sys_timer.c | 43 +-- drivers/timer/hpet.c | 104 ++++---- drivers/timer/ite_it8xxx2_timer.c | 6 +- drivers/timer/leon_gptimer.c | 6 +- drivers/timer/litex_timer.c | 5 +- drivers/timer/mchp_xec_rtos_timer.c | 64 ++--- drivers/timer/mcux_lptmr_timer.c | 6 +- drivers/timer/mcux_os_timer.c | 52 ++-- drivers/timer/native_posix_timer.c | 43 +-- drivers/timer/npcx_itim_timer.c | 1 + drivers/timer/nrf_rtc_timer.c | 84 +++--- drivers/timer/rcar_cmt_timer.c | 26 +- drivers/timer/riscv_machine_timer.c | 26 +- drivers/timer/rv32m1_lptmr_timer.c | 30 ++- drivers/timer/sam0_rtc_timer.c | 132 +++++----- drivers/timer/stm32_lptim_timer.c | 274 ++++++++++---------- drivers/timer/sys_clock_init.c | 10 - drivers/timer/xlnx_psttc_timer.c | 90 ++++--- drivers/timer/xtensa_sys_timer.c | 24 +- include/drivers/timer/system_timer.h | 12 +- 29 files changed, 724 insertions(+), 648 deletions(-) diff --git a/boards/arm/qemu_cortex_m0/nrf_timer_timer.c b/boards/arm/qemu_cortex_m0/nrf_timer_timer.c index 701c4494188..725eb182ecc 100644 --- a/boards/arm/qemu_cortex_m0/nrf_timer_timer.c +++ b/boards/arm/qemu_cortex_m0/nrf_timer_timer.c @@ -160,31 +160,6 @@ void timer0_nrf_isr(void *arg) sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : (dticks > 0)); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - /* FIXME switch to 1 MHz once this is fixed in QEMU */ - nrf_timer_frequency_set(TIMER, NRF_TIMER_FREQ_2MHz); - nrf_timer_bit_width_set(TIMER, NRF_TIMER_BIT_WIDTH_32); - - IRQ_CONNECT(TIMER0_IRQn, 1, timer0_nrf_isr, 0, 0); - irq_enable(TIMER0_IRQn); - - nrf_timer_task_trigger(TIMER, NRF_TIMER_TASK_CLEAR); - nrf_timer_task_trigger(TIMER, NRF_TIMER_TASK_START); - - if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - set_comparator(counter() + CYC_PER_TICK); - } - - event_clear(); - NVIC_ClearPendingIRQ(TIMER0_IRQn); - int_enable(); - - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -255,3 +230,31 @@ uint32_t sys_clock_cycle_get_32(void) k_spin_unlock(&lock, key); return ret; } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* FIXME switch to 1 MHz once this is fixed in QEMU */ + nrf_timer_frequency_set(TIMER, NRF_TIMER_FREQ_2MHz); + nrf_timer_bit_width_set(TIMER, NRF_TIMER_BIT_WIDTH_32); + + IRQ_CONNECT(TIMER0_IRQn, 1, timer0_nrf_isr, 0, 0); + irq_enable(TIMER0_IRQn); + + nrf_timer_task_trigger(TIMER, NRF_TIMER_TASK_CLEAR); + nrf_timer_task_trigger(TIMER, NRF_TIMER_TASK_START); + + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + set_comparator(counter() + CYC_PER_TICK); + } + + event_clear(); + NVIC_ClearPendingIRQ(TIMER0_IRQn); + int_enable(); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/altera_avalon_timer_hal.c b/drivers/timer/altera_avalon_timer_hal.c index 7595a86fbbe..886a8f8b6dc 100644 --- a/drivers/timer/altera_avalon_timer_hal.c +++ b/drivers/timer/altera_avalon_timer_hal.c @@ -42,24 +42,6 @@ static void timer_irq_handler(const void *unused) wrapped_announce(_sys_idle_elapsed_ticks); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE, - k_ticks_to_cyc_floor32(1) & 0xFFFF); - IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE, - (k_ticks_to_cyc_floor32(1) >> 16) & 0xFFFF); - - IRQ_CONNECT(TIMER_0_IRQ, 0, timer_irq_handler, NULL, 0); - irq_enable(TIMER_0_IRQ); - - alt_avalon_timer_sc_init((void *)TIMER_0_BASE, 0, - TIMER_0_IRQ, k_ticks_to_cyc_floor32(1)); - - return 0; -} - uint32_t sys_clock_cycle_get_32(void) { /* Per the Altera Embedded IP Peripherals guide, you cannot @@ -85,3 +67,24 @@ uint32_t sys_clock_elapsed(void) { return 0; } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE, + k_ticks_to_cyc_floor32(1) & 0xFFFF); + IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE, + (k_ticks_to_cyc_floor32(1) >> 16) & 0xFFFF); + + IRQ_CONNECT(TIMER_0_IRQ, 0, timer_irq_handler, NULL, 0); + irq_enable(TIMER_0_IRQ); + + alt_avalon_timer_sc_init((void *)TIMER_0_BASE, 0, + TIMER_0_IRQ, k_ticks_to_cyc_floor32(1)); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/apic_timer.c b/drivers/timer/apic_timer.c index 9a803f2d426..a5c33a2a103 100644 --- a/drivers/timer/apic_timer.c +++ b/drivers/timer/apic_timer.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -213,7 +214,7 @@ uint32_t sys_clock_cycle_get_32(void) #endif -int sys_clock_driver_init(const struct device *dev) +static int sys_clock_driver_init(const struct device *dev) { uint32_t val; @@ -240,3 +241,6 @@ int sys_clock_driver_init(const struct device *dev) return 0; } + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index 24453ab0c9e..67a4cbadd59 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -2,6 +2,7 @@ * Copyright (c) 2021 Intel Corporation * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -154,7 +155,7 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t * : "a"(*eax), "c"(*ecx)); } -int sys_clock_driver_init(const struct device *dev) +static int sys_clock_driver_init(const struct device *dev) { #ifdef CONFIG_ASSERT uint32_t eax, ebx, ecx, edx; @@ -200,3 +201,6 @@ int sys_clock_driver_init(const struct device *dev) return 0; } + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/arcv2_timer0.c b/drivers/timer/arcv2_timer0.c index 931691cd7d5..8ff594c9219 100644 --- a/drivers/timer/arcv2_timer0.c +++ b/drivers/timer/arcv2_timer0.c @@ -4,7 +4,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ - +#include #include #include #include @@ -267,50 +267,6 @@ static void timer_int_handler(const void *unused) } - -/** - * - * @brief Initialize and enable the system clock - * - * This routine is used to program the ARCv2 timer to deliver interrupts at the - * rate specified via the CYC_PER_TICK. - * - * @return 0 - */ -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - /* ensure that the timer will not generate interrupts */ - timer0_control_register_set(0); - -#if SMP_TIMER_DRIVER - IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY, - timer_int_handler, NULL, 0); - - timer0_limit_register_set(CYC_PER_TICK - 1); - last_time = z_arc_connect_gfrc_read(); - start_time = last_time; -#else - last_load = CYC_PER_TICK; - overflow_cycles = 0; - announced_cycles = 0; - - IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY, - timer_int_handler, NULL, 0); - - timer0_limit_register_set(last_load - 1); -#endif - timer0_count_register_set(0); - timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE); - - /* everything has been configured: safe to enable the interrupt */ - - irq_enable(IRQ_TIMER0); - - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { /* If the kernel allows us to miss tick announcements in idle, @@ -459,3 +415,49 @@ void smp_timer_init(void) irq_enable(IRQ_TIMER0); } #endif + +/** + * + * @brief Initialize and enable the system clock + * + * This routine is used to program the ARCv2 timer to deliver interrupts at the + * rate specified via the CYC_PER_TICK. + * + * @return 0 + */ +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* ensure that the timer will not generate interrupts */ + timer0_control_register_set(0); + +#if SMP_TIMER_DRIVER + IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY, + timer_int_handler, NULL, 0); + + timer0_limit_register_set(CYC_PER_TICK - 1); + last_time = z_arc_connect_gfrc_read(); + start_time = last_time; +#else + last_load = CYC_PER_TICK; + overflow_cycles = 0; + announced_cycles = 0; + + IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY, + timer_int_handler, NULL, 0); + + timer0_limit_register_set(last_load - 1); +#endif + timer0_count_register_set(0); + timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE); + + /* everything has been configured: safe to enable the interrupt */ + + irq_enable(IRQ_TIMER0); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/arm_arch_timer.c b/drivers/timer/arm_arch_timer.c index 4e6891b8f69..63a81718548 100644 --- a/drivers/timer/arm_arch_timer.c +++ b/drivers/timer/arm_arch_timer.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ - +#include #include #include #include @@ -85,21 +85,6 @@ static void arm_arch_timer_compare_isr(const void *arg) sys_clock_announce(delta_ticks); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - IRQ_CONNECT(ARM_ARCH_TIMER_IRQ, ARM_ARCH_TIMER_PRIO, - arm_arch_timer_compare_isr, NULL, ARM_ARCH_TIMER_FLAGS); - arm_arch_timer_init(); - arm_arch_timer_set_compare(arm_arch_timer_count() + CYC_PER_TICK); - arm_arch_timer_enable(true); - irq_enable(ARM_ARCH_TIMER_IRQ); - arm_arch_timer_set_irq_mask(false); - - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { #if defined(CONFIG_TICKLESS_KERNEL) @@ -192,3 +177,21 @@ void smp_timer_init(void) arm_arch_timer_set_irq_mask(false); } #endif + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + IRQ_CONNECT(ARM_ARCH_TIMER_IRQ, ARM_ARCH_TIMER_PRIO, + arm_arch_timer_compare_isr, NULL, ARM_ARCH_TIMER_FLAGS); + arm_arch_timer_init(); + arm_arch_timer_set_compare(arm_arch_timer_count() + CYC_PER_TICK); + arm_arch_timer_enable(true); + irq_enable(ARM_ARCH_TIMER_IRQ); + arm_arch_timer_set_irq_mask(false); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/cavs_timer.c b/drivers/timer/cavs_timer.c index 92c29e3f4ed..7ccb92b790b 100644 --- a/drivers/timer/cavs_timer.c +++ b/drivers/timer/cavs_timer.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ - +#include #include #include #include @@ -118,18 +118,6 @@ static void compare_isr(const void *arg) sys_clock_announce(dticks); } -/* Runs on core 0 only */ -int sys_clock_driver_init(const struct device *dev) -{ - uint64_t curr = count(); - - IRQ_CONNECT(TIMER_IRQ, 0, compare_isr, 0, 0); - set_compare(curr + CYC_PER_TICK); - last_count = curr; - irq_enable(TIMER_IRQ); - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -195,3 +183,18 @@ void smp_timer_init(void) CAVS_INTCTRL[arch_curr_cpu()->id].l2.clear = CAVS_L2_DWCT0; irq_enable(TIMER_IRQ); } + +/* Runs on core 0 only */ +static int sys_clock_driver_init(const struct device *dev) +{ + uint64_t curr = count(); + + IRQ_CONNECT(TIMER_IRQ, 0, compare_isr, 0, 0); + set_compare(curr + CYC_PER_TICK); + last_count = curr; + irq_enable(TIMER_IRQ); + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/cc13x2_cc26x2_rtc_timer.c b/drivers/timer/cc13x2_cc26x2_rtc_timer.c index 7950d5be296..e90b6f43166 100644 --- a/drivers/timer/cc13x2_cc26x2_rtc_timer.c +++ b/drivers/timer/cc13x2_cc26x2_rtc_timer.c @@ -15,6 +15,7 @@ * the comparator value set is reached. */ +#include #include #include #include @@ -183,24 +184,6 @@ static void startDevice(void) irq_unlock(key); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - rtc_last = 0U; - - initDevice(); - startDevice(); - - /* Enable RTC interrupt. */ - IRQ_CONNECT(DT_INST_IRQN(0), - DT_INST_IRQ(0, priority), - rtc_isr, 0, 0); - irq_enable(DT_INST_IRQN(0)); - - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -247,3 +230,24 @@ uint64_t sys_clock_cycle_get_64(void) { return AONRTCCurrent64BitValueGet() / RTC_COUNTS_PER_CYCLE; } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + rtc_last = 0U; + + initDevice(); + startDevice(); + + /* Enable RTC interrupt. */ + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + rtc_isr, 0, 0); + irq_enable(DT_INST_IRQN(0)); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/cortex_m_systick.c b/drivers/timer/cortex_m_systick.c index 54c6ca766d3..4679ef2bafd 100644 --- a/drivers/timer/cortex_m_systick.c +++ b/drivers/timer/cortex_m_systick.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -149,21 +150,6 @@ void sys_clock_isr(void *arg) z_arm_int_exit(); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - NVIC_SetPriority(SysTick_IRQn, _IRQ_PRIO_OFFSET); - last_load = CYC_PER_TICK - 1; - overflow_cyc = 0U; - SysTick->LOAD = last_load; - SysTick->VAL = 0; /* resets timer to last_load */ - SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_CLKSOURCE_Msk); - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { /* Fast CPUs and a 24 bit counter mean that even idle systems @@ -279,3 +265,21 @@ void sys_clock_disable(void) { SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + NVIC_SetPriority(SysTick_IRQn, _IRQ_PRIO_OFFSET); + last_load = CYC_PER_TICK - 1; + overflow_cyc = 0U; + SysTick->LOAD = last_load; + SysTick->VAL = 0; /* resets timer to last_load */ + SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_CLKSOURCE_Msk); + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/esp32c3_sys_timer.c b/drivers/timer/esp32c3_sys_timer.c index 51416c050c1..11c398d4c03 100644 --- a/drivers/timer/esp32c3_sys_timer.c +++ b/drivers/timer/esp32c3_sys_timer.c @@ -67,26 +67,6 @@ static void sys_timer_isr(const void *arg) sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - esp_intr_alloc(DT_IRQN(DT_NODELABEL(systimer0)), - 0, - sys_timer_isr, - NULL, - NULL); - - systimer_hal_init(); - systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1); - systimer_hal_enable_counter(SYSTIMER_COUNTER_1); - systimer_hal_counter_can_stall_by_cpu(SYSTIMER_COUNTER_1, 0, true); - last_count = systimer_alarm(); - set_systimer_alarm(last_count + CYC_PER_TICK); - - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -139,3 +119,26 @@ uint64_t sys_clock_cycle_get_64(void) { return systimer_alarm(); } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + esp_intr_alloc(DT_IRQN(DT_NODELABEL(systimer0)), + 0, + sys_timer_isr, + NULL, + NULL); + + systimer_hal_init(); + systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1); + systimer_hal_enable_counter(SYSTIMER_COUNTER_1); + systimer_hal_counter_can_stall_by_cpu(SYSTIMER_COUNTER_1, 0, true); + last_count = systimer_alarm(); + set_systimer_alarm(last_count + CYC_PER_TICK); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/hpet.c b/drivers/timer/hpet.c index 29ea1bd0cb6..ca813e04421 100644 --- a/drivers/timer/hpet.c +++ b/drivers/timer/hpet.c @@ -5,6 +5,7 @@ */ #define DT_DRV_COMPAT intel_hpet +#include #include #include #include @@ -316,56 +317,6 @@ static void config_timer0(unsigned int irq) hpet_timer_conf_set(val); } -__boot_func -int sys_clock_driver_init(const struct device *dev) -{ - extern int z_clock_hw_cycles_per_sec; - uint32_t hz, reg; - - ARG_UNUSED(dev); - ARG_UNUSED(hz); - ARG_UNUSED(z_clock_hw_cycles_per_sec); - - DEVICE_MMIO_TOPLEVEL_MAP(hpet_regs, K_MEM_CACHE_NONE); - -#if DT_INST_IRQ_HAS_CELL(0, sense) - IRQ_CONNECT(DT_INST_IRQN(0), - DT_INST_IRQ(0, priority), - hpet_isr, 0, DT_INST_IRQ(0, sense)); -#else - IRQ_CONNECT(DT_INST_IRQN(0), - DT_INST_IRQ(0, priority), - hpet_isr, 0, 0); -#endif - config_timer0(DT_INST_IRQN(0)); - irq_enable(DT_INST_IRQN(0)); - -#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME - hz = (uint32_t)(HPET_COUNTER_CLK_PERIOD / hpet_counter_clk_period_get()); - z_clock_hw_cycles_per_sec = hz; - cyc_per_tick = hz / CONFIG_SYS_CLOCK_TICKS_PER_SEC; -#endif - - /* Note: we set the legacy routing bit, because otherwise - * nothing in Zephyr disables the PIT which then fires - * interrupts into the same IRQ. But that means we're then - * forced to use IRQ2 contra the way the kconfig IRQ selection - * is supposed to work. Should fix this. - */ - reg = hpet_gconf_get(); - reg |= GCONF_LR | GCONF_ENABLE; - hpet_gconf_set(reg); - - last_count = hpet_counter_get(); - if (cyc_per_tick >= HPET_CMP_MIN_DELAY) { - hpet_timer_comparator_set(last_count + cyc_per_tick); - } else { - hpet_timer_comparator_set(last_count + HPET_CMP_MIN_DELAY); - } - - return 0; -} - __boot_func void smp_timer_init(void) { @@ -453,3 +404,56 @@ void sys_clock_idle_exit(void) reg |= GCONF_ENABLE; hpet_gconf_set(reg); } + +__boot_func +static int sys_clock_driver_init(const struct device *dev) +{ + extern int z_clock_hw_cycles_per_sec; + uint32_t hz, reg; + + ARG_UNUSED(dev); + ARG_UNUSED(hz); + ARG_UNUSED(z_clock_hw_cycles_per_sec); + + DEVICE_MMIO_TOPLEVEL_MAP(hpet_regs, K_MEM_CACHE_NONE); + +#if DT_INST_IRQ_HAS_CELL(0, sense) + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + hpet_isr, 0, DT_INST_IRQ(0, sense)); +#else + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + hpet_isr, 0, 0); +#endif + config_timer0(DT_INST_IRQN(0)); + irq_enable(DT_INST_IRQN(0)); + +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + hz = (uint32_t)(HPET_COUNTER_CLK_PERIOD / hpet_counter_clk_period_get()); + z_clock_hw_cycles_per_sec = hz; + cyc_per_tick = hz / CONFIG_SYS_CLOCK_TICKS_PER_SEC; +#endif + + /* Note: we set the legacy routing bit, because otherwise + * nothing in Zephyr disables the PIT which then fires + * interrupts into the same IRQ. But that means we're then + * forced to use IRQ2 contra the way the kconfig IRQ selection + * is supposed to work. Should fix this. + */ + reg = hpet_gconf_get(); + reg |= GCONF_LR | GCONF_ENABLE; + hpet_gconf_set(reg); + + last_count = hpet_counter_get(); + if (cyc_per_tick >= HPET_CMP_MIN_DELAY) { + hpet_timer_comparator_set(last_count + cyc_per_tick); + } else { + hpet_timer_comparator_set(last_count + HPET_CMP_MIN_DELAY); + } + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/ite_it8xxx2_timer.c b/drivers/timer/ite_it8xxx2_timer.c index 1e070034edb..297bbe1bd10 100644 --- a/drivers/timer/ite_it8xxx2_timer.c +++ b/drivers/timer/ite_it8xxx2_timer.c @@ -5,6 +5,7 @@ #define DT_DRV_COMPAT ite_it8xxx2_timer +#include #include #include #include @@ -331,7 +332,7 @@ static int timer_init(enum ext_timer_idx ext_timer, return 0; } -int sys_clock_driver_init(const struct device *dev) +static int sys_clock_driver_init(const struct device *dev) { int ret; @@ -372,3 +373,6 @@ int sys_clock_driver_init(const struct device *dev) return 0; } + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/leon_gptimer.c b/drivers/timer/leon_gptimer.c index 380cfd0f5c0..3409ba671f4 100644 --- a/drivers/timer/leon_gptimer.c +++ b/drivers/timer/leon_gptimer.c @@ -12,6 +12,7 @@ #define DT_DRV_COMPAT gaisler_gptimer +#include #include #include @@ -101,7 +102,7 @@ static void init_downcounter(volatile struct gptimer_timer_regs *tmr) tmr->ctrl = GPTIMER_CTRL_LD | GPTIMER_CTRL_RS | GPTIMER_CTRL_EN; } -int sys_clock_driver_init(const struct device *dev) +static int sys_clock_driver_init(const struct device *dev) { ARG_UNUSED(dev); const int timer_interrupt = get_timer_irq(); @@ -127,3 +128,6 @@ int sys_clock_driver_init(const struct device *dev) irq_enable(timer_interrupt); return 0; } + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/litex_timer.c b/drivers/timer/litex_timer.c index 847d4211b11..c44795d883b 100644 --- a/drivers/timer/litex_timer.c +++ b/drivers/timer/litex_timer.c @@ -72,7 +72,7 @@ uint32_t sys_clock_elapsed(void) return 0; } -int sys_clock_driver_init(const struct device *dev) +static int sys_clock_driver_init(const struct device *dev) { ARG_UNUSED(dev); IRQ_CONNECT(TIMER_IRQ, DT_INST_IRQ(0, priority), @@ -94,3 +94,6 @@ int sys_clock_driver_init(const struct device *dev) return 0; } + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/mchp_xec_rtos_timer.c b/drivers/timer/mchp_xec_rtos_timer.c index 7dd853dd13f..e3307d0c1d2 100644 --- a/drivers/timer/mchp_xec_rtos_timer.c +++ b/drivers/timer/mchp_xec_rtos_timer.c @@ -6,6 +6,7 @@ #define DT_DRV_COMPAT microchip_xec_rtos_timer +#include #include #include #include @@ -366,7 +367,37 @@ void sys_clock_disable(void) TIMER_REGS->CTRL = 0U; } -int sys_clock_driver_init(const struct device *dev) +#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT + +/* + * We implement custom busy wait using a MEC1501 basic timer running on + * the 48MHz clock domain. This code is here for future power management + * save/restore of the timer context. + */ + +/* + * 32-bit basic timer 0 configured for 1MHz count up, auto-reload, + * and no interrupt generation. + */ +void arch_busy_wait(uint32_t usec_to_wait) +{ + if (usec_to_wait == 0) { + return; + } + + uint32_t start = BTMR32_0_REGS->CNT; + + for (;;) { + uint32_t curr = BTMR32_0_REGS->CNT; + + if ((curr - start) >= usec_to_wait) { + break; + } + } +} +#endif + +static int sys_clock_driver_init(const struct device *dev) { ARG_UNUSED(dev); @@ -413,32 +444,5 @@ int sys_clock_driver_init(const struct device *dev) return 0; } -#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT - -/* - * We implement custom busy wait using a MEC1501 basic timer running on - * the 48MHz clock domain. This code is here for future power management - * save/restore of the timer context. - */ - -/* - * 32-bit basic timer 0 configured for 1MHz count up, auto-reload, - * and no interrupt generation. - */ -void arch_busy_wait(uint32_t usec_to_wait) -{ - if (usec_to_wait == 0) { - return; - } - - uint32_t start = BTMR32_0_REGS->CNT; - - for (;;) { - uint32_t curr = BTMR32_0_REGS->CNT; - - if ((curr - start) >= usec_to_wait) { - break; - } - } -} -#endif +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/mcux_lptmr_timer.c b/drivers/timer/mcux_lptmr_timer.c index f43fc529b62..ade1cfd1327 100644 --- a/drivers/timer/mcux_lptmr_timer.c +++ b/drivers/timer/mcux_lptmr_timer.c @@ -6,6 +6,7 @@ #define DT_DRV_COMPAT nxp_kinetis_lptmr +#include #include #include @@ -91,7 +92,7 @@ static void mcux_lptmr_timer_isr(void *arg) LPTMR_ClearStatusFlags(LPTMR_BASE, kLPTMR_TimerCompareFlag); } -int sys_clock_driver_init(const struct device *dev) +static int sys_clock_driver_init(const struct device *dev) { lptmr_config_t config; @@ -120,3 +121,6 @@ int sys_clock_driver_init(const struct device *dev) return 0; } + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/mcux_os_timer.c b/drivers/timer/mcux_os_timer.c index 0849e56bc81..d732913403e 100644 --- a/drivers/timer/mcux_os_timer.c +++ b/drivers/timer/mcux_os_timer.c @@ -6,6 +6,7 @@ #define DT_DRV_COMPAT nxp_os_timer +#include #include #include #include @@ -50,30 +51,6 @@ void mcux_lpc_ostick_isr(void *arg) sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1); } -int sys_clock_driver_init(const struct device *device) -{ - ARG_UNUSED(device); - - /* Configure event timer's ISR */ - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - mcux_lpc_ostick_isr, NULL, 0); - - base = (OSTIMER_Type *)DT_INST_REG_ADDR(0); - - EnableDeepSleepIRQ(DT_INST_IRQN(0)); - - /* Initialize the OS timer, setting clock configuration. */ - OSTIMER_Init(base); - - last_count = OSTIMER_GetCurrentTimerValue(base); - OSTIMER_SetMatchValue(base, last_count + CYC_PER_TICK, NULL); - - /* Enable event timer interrupt */ - irq_enable(DT_INST_IRQN(0)); - - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -132,3 +109,30 @@ uint64_t sys_clock_cycle_get_64(void) { return OSTIMER_GetCurrentTimerValue(base); } + +static int sys_clock_driver_init(const struct device *device) +{ + ARG_UNUSED(device); + + /* Configure event timer's ISR */ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), + mcux_lpc_ostick_isr, NULL, 0); + + base = (OSTIMER_Type *)DT_INST_REG_ADDR(0); + + EnableDeepSleepIRQ(DT_INST_IRQN(0)); + + /* Initialize the OS timer, setting clock configuration. */ + OSTIMER_Init(base); + + last_count = OSTIMER_GetCurrentTimerValue(base); + OSTIMER_SetMatchValue(base, last_count + CYC_PER_TICK, NULL); + + /* Enable event timer interrupt */ + irq_enable(DT_INST_IRQN(0)); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/native_posix_timer.c b/drivers/timer/native_posix_timer.c index 998eff6cf74..62b492ee053 100644 --- a/drivers/timer/native_posix_timer.c +++ b/drivers/timer/native_posix_timer.c @@ -60,26 +60,6 @@ void np_timer_isr_test_hook(const void *arg) np_timer_isr(NULL); } -/* - * @brief Initialize system timer driver - * - * Enable the hw timer, setting its tick period, and setup its interrupt - */ -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - tick_period = 1000000ul / CONFIG_SYS_CLOCK_TICKS_PER_SEC; - - last_tick_time = hwm_get_time(); - hwtimer_enable(tick_period); - - IRQ_CONNECT(TIMER_TICK_IRQ, 1, np_timer_isr, 0, 0); - irq_enable(TIMER_TICK_IRQ); - - return 0; -} - /** * @brief Set system clock timeout * @@ -143,3 +123,26 @@ void sys_clock_disable(void) hwtimer_set_silent_ticks(INT64_MAX); } #endif /* CONFIG_SYSTEM_CLOCK_DISABLE */ + +/* + * @brief Initialize system timer driver + * + * Enable the hw timer, setting its tick period, and setup its interrupt + */ +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + tick_period = 1000000ul / CONFIG_SYS_CLOCK_TICKS_PER_SEC; + + last_tick_time = hwm_get_time(); + hwtimer_enable(tick_period); + + IRQ_CONNECT(TIMER_TICK_IRQ, 1, np_timer_isr, 0, 0); + irq_enable(TIMER_TICK_IRQ); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/npcx_itim_timer.c b/drivers/timer/npcx_itim_timer.c index 8c3bf6078d2..3fbc9c95b0c 100644 --- a/drivers/timer/npcx_itim_timer.c +++ b/drivers/timer/npcx_itim_timer.c @@ -34,6 +34,7 @@ * "sleep/deep sleep" power state if CONFIG_PM is enabled. */ +#include #include #include #include diff --git a/drivers/timer/nrf_rtc_timer.c b/drivers/timer/nrf_rtc_timer.c index c403eaee477..9b52f6600d9 100644 --- a/drivers/timer/nrf_rtc_timer.c +++ b/drivers/timer/nrf_rtc_timer.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -311,46 +312,6 @@ void z_nrf_rtc_timer_chan_free(int32_t chan) atomic_or(&alloc_mask, BIT(chan)); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - static const enum nrf_lfclk_start_mode mode = - IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT) ? - CLOCK_CONTROL_NRF_LF_START_NOWAIT : - (IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY) ? - CLOCK_CONTROL_NRF_LF_START_AVAILABLE : - CLOCK_CONTROL_NRF_LF_START_STABLE); - - /* TODO: replace with counter driver to access RTC */ - nrf_rtc_prescaler_set(RTC, 0); - for (int32_t chan = 0; chan < CHAN_COUNT; chan++) { - nrf_rtc_int_enable(RTC, RTC_CHANNEL_INT_MASK(chan)); - } - - NVIC_ClearPendingIRQ(RTC_IRQn); - - IRQ_CONNECT(RTC_IRQn, DT_IRQ(DT_NODELABEL(RTC_LABEL), priority), - rtc_nrf_isr, 0, 0); - irq_enable(RTC_IRQn); - - nrf_rtc_task_trigger(RTC, NRF_RTC_TASK_CLEAR); - nrf_rtc_task_trigger(RTC, NRF_RTC_TASK_START); - - int_mask = BIT_MASK(CHAN_COUNT); - if (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT) { - alloc_mask = BIT_MASK(EXT_CHAN_COUNT) << 1; - } - - if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - compare_set(0, counter() + CYC_PER_TICK, - sys_clock_timeout_handler, NULL); - } - - z_nrf_clock_control_lf_on(mode); - - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -409,3 +370,46 @@ uint32_t sys_clock_cycle_get_32(void) k_spin_unlock(&lock, key); return ret; } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + static const enum nrf_lfclk_start_mode mode = + IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT) ? + CLOCK_CONTROL_NRF_LF_START_NOWAIT : + (IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY) ? + CLOCK_CONTROL_NRF_LF_START_AVAILABLE : + CLOCK_CONTROL_NRF_LF_START_STABLE); + + /* TODO: replace with counter driver to access RTC */ + nrf_rtc_prescaler_set(RTC, 0); + for (int32_t chan = 0; chan < CHAN_COUNT; chan++) { + nrf_rtc_int_enable(RTC, RTC_CHANNEL_INT_MASK(chan)); + } + + NVIC_ClearPendingIRQ(RTC_IRQn); + + IRQ_CONNECT(RTC_IRQn, DT_IRQ(DT_NODELABEL(RTC_LABEL), priority), + rtc_nrf_isr, 0, 0); + irq_enable(RTC_IRQn); + + nrf_rtc_task_trigger(RTC, NRF_RTC_TASK_CLEAR); + nrf_rtc_task_trigger(RTC, NRF_RTC_TASK_START); + + int_mask = BIT_MASK(CHAN_COUNT); + if (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT) { + alloc_mask = BIT_MASK(EXT_CHAN_COUNT) << 1; + } + + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + compare_set(0, counter() + CYC_PER_TICK, + sys_clock_timeout_handler, NULL); + } + + z_nrf_clock_control_lf_on(mode); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/rcar_cmt_timer.c b/drivers/timer/rcar_cmt_timer.c index c7d75679aaa..d68fea0a248 100644 --- a/drivers/timer/rcar_cmt_timer.c +++ b/drivers/timer/rcar_cmt_timer.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -66,13 +67,24 @@ static void cmt_isr(void *arg) sys_clock_announce(1); } +uint32_t sys_clock_elapsed(void) +{ + /* Always return 0 for tickful operation */ + return 0; +} + +uint32_t sys_clock_cycle_get_32(void) +{ + return sys_read32(TIMER_BASE_ADDR + CMCNT1_OFFSET); +} + /* * Initialize both channels at same frequency, * Set the first one to generates interrupt at CYCLES_PER_TICK. * The second one is used for cycles count, the match value is set * at max uint32_t. */ -int sys_clock_driver_init(const struct device *device) +static int sys_clock_driver_init(const struct device *device) { const struct device *clk; uint32_t reg_val; @@ -140,13 +152,5 @@ int sys_clock_driver_init(const struct device *device) return 0; } -uint32_t sys_clock_elapsed(void) -{ - /* Always return 0 for tickful operation */ - return 0; -} - -uint32_t sys_clock_cycle_get_32(void) -{ - return sys_read32(TIMER_BASE_ADDR + CMCNT1_OFFSET); -} +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/riscv_machine_timer.c b/drivers/timer/riscv_machine_timer.c index 7d9ace9d637..9a5b367d466 100644 --- a/drivers/timer/riscv_machine_timer.c +++ b/drivers/timer/riscv_machine_timer.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -79,17 +80,6 @@ static void timer_isr(const void *arg) sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - IRQ_CONNECT(RISCV_MACHINE_TIMER_IRQ, 0, timer_isr, NULL, 0); - last_count = mtime(); - set_mtimecmp(last_count + CYC_PER_TICK); - irq_enable(RISCV_MACHINE_TIMER_IRQ); - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -152,3 +142,17 @@ uint64_t sys_clock_cycle_get_64(void) { return mtime(); } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + IRQ_CONNECT(RISCV_MACHINE_TIMER_IRQ, 0, timer_isr, NULL, 0); + last_count = mtime(); + set_mtimecmp(last_count + CYC_PER_TICK); + irq_enable(RISCV_MACHINE_TIMER_IRQ); + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/rv32m1_lptmr_timer.c b/drivers/timer/rv32m1_lptmr_timer.c index 62fba35d65c..db6101fda4c 100644 --- a/drivers/timer/rv32m1_lptmr_timer.c +++ b/drivers/timer/rv32m1_lptmr_timer.c @@ -6,6 +6,7 @@ #define DT_DRV_COMPAT openisa_rv32m1_lptmr +#include #include #include #include @@ -53,7 +54,20 @@ static void lptmr_irq_handler(const struct device *unused) sys_clock_announce(1); /* Poke the scheduler. */ } -int sys_clock_driver_init(const struct device *unused) +uint32_t sys_clock_cycle_get_32(void) +{ + return cycle_count + SYSTEM_TIMER_INSTANCE->CNR; +} + +/* + * Since we're not tickless, this is identically zero. + */ +uint32_t sys_clock_elapsed(void) +{ + return 0; +} + +static int sys_clock_driver_init(const struct device *unused) { uint32_t csr, psr, sircdiv; /* LPTMR registers */ @@ -131,15 +145,5 @@ int sys_clock_driver_init(const struct device *unused) return 0; } -uint32_t sys_clock_cycle_get_32(void) -{ - return cycle_count + SYSTEM_TIMER_INSTANCE->CNR; -} - -/* - * Since we're not tickless, this is identically zero. - */ -uint32_t sys_clock_elapsed(void) -{ - return 0; -} +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/sam0_rtc_timer.c b/drivers/timer/sam0_rtc_timer.c index be09e70d563..e3f2a779db0 100644 --- a/drivers/timer/sam0_rtc_timer.c +++ b/drivers/timer/sam0_rtc_timer.c @@ -16,6 +16,7 @@ * generate an interrupt every tick. */ +#include #include #include #include @@ -175,7 +176,71 @@ static void rtc_isr(const void *arg) #endif /* CONFIG_TICKLESS_KERNEL */ } -int sys_clock_driver_init(const struct device *dev) +void sys_clock_set_timeout(int32_t ticks, bool idle) +{ + ARG_UNUSED(idle); + +#ifdef CONFIG_TICKLESS_KERNEL + + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; + ticks = CLAMP(ticks - 1, 0, (int32_t) MAX_TICKS); + + /* Compute number of RTC cycles until the next timeout. */ + uint32_t count = rtc_count(); + uint32_t timeout = ticks * CYCLES_PER_TICK + count % CYCLES_PER_TICK; + + /* Round to the nearest tick boundary. */ + timeout = (timeout + CYCLES_PER_TICK - 1) / CYCLES_PER_TICK + * CYCLES_PER_TICK; + + if (timeout < TICK_THRESHOLD) { + timeout += CYCLES_PER_TICK; + } + + rtc_sync(); + RTC0->COMP[0].reg = count + timeout; + +#else /* !CONFIG_TICKLESS_KERNEL */ + + if (ticks == K_TICKS_FOREVER) { + /* Disable comparator for K_TICKS_FOREVER and other negative + * values. + */ + rtc_timeout = rtc_counter; + return; + } + + if (ticks < 1) { + ticks = 1; + } + + /* Avoid race condition between reading counter and ISR incrementing + * it. + */ + int key = irq_lock(); + + rtc_timeout = rtc_counter + ticks; + irq_unlock(key); + +#endif /* CONFIG_TICKLESS_KERNEL */ +} + +uint32_t sys_clock_elapsed(void) +{ +#ifdef CONFIG_TICKLESS_KERNEL + return (rtc_count() - rtc_last) / CYCLES_PER_TICK; +#else + return rtc_counter - rtc_last; +#endif +} + +uint32_t sys_clock_cycle_get_32(void) +{ + /* Just return the absolute value of RTC cycle counter. */ + return rtc_count(); +} + +static int sys_clock_driver_init(const struct device *dev) { ARG_UNUSED(dev); @@ -252,66 +317,5 @@ int sys_clock_driver_init(const struct device *dev) return 0; } -void sys_clock_set_timeout(int32_t ticks, bool idle) -{ - ARG_UNUSED(idle); - -#ifdef CONFIG_TICKLESS_KERNEL - - ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; - ticks = CLAMP(ticks - 1, 0, (int32_t) MAX_TICKS); - - /* Compute number of RTC cycles until the next timeout. */ - uint32_t count = rtc_count(); - uint32_t timeout = ticks * CYCLES_PER_TICK + count % CYCLES_PER_TICK; - - /* Round to the nearest tick boundary. */ - timeout = (timeout + CYCLES_PER_TICK - 1) / CYCLES_PER_TICK - * CYCLES_PER_TICK; - - if (timeout < TICK_THRESHOLD) { - timeout += CYCLES_PER_TICK; - } - - rtc_sync(); - RTC0->COMP[0].reg = count + timeout; - -#else /* !CONFIG_TICKLESS_KERNEL */ - - if (ticks == K_TICKS_FOREVER) { - /* Disable comparator for K_TICKS_FOREVER and other negative - * values. - */ - rtc_timeout = rtc_counter; - return; - } - - if (ticks < 1) { - ticks = 1; - } - - /* Avoid race condition between reading counter and ISR incrementing - * it. - */ - int key = irq_lock(); - - rtc_timeout = rtc_counter + ticks; - irq_unlock(key); - -#endif /* CONFIG_TICKLESS_KERNEL */ -} - -uint32_t sys_clock_elapsed(void) -{ -#ifdef CONFIG_TICKLESS_KERNEL - return (rtc_count() - rtc_last) / CYCLES_PER_TICK; -#else - return rtc_counter - rtc_last; -#endif -} - -uint32_t sys_clock_cycle_get_32(void) -{ - /* Just return the absolute value of RTC cycle counter. */ - return rtc_count(); -} +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/stm32_lptim_timer.c b/drivers/timer/stm32_lptim_timer.c index 485499fa819..bec9761e66c 100644 --- a/drivers/timer/stm32_lptim_timer.c +++ b/drivers/timer/stm32_lptim_timer.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -78,141 +79,6 @@ static void lptim_irq_handler(const struct device *unused) } } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - /* enable LPTIM clock source */ -#if defined(LL_APB1_GRP1_PERIPH_LPTIM1) - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPTIM1); - LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_LPTIM1); -#elif defined(LL_APB3_GRP1_PERIPH_LPTIM1) - LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_LPTIM1); - LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_LPTIM1AMEN); -#endif - -#if defined(CONFIG_STM32_LPTIM_CLOCK_LSI) - /* enable LSI clock */ -#ifdef CONFIG_SOC_SERIES_STM32WBX - LL_RCC_LSI1_Enable(); - while (!LL_RCC_LSI1_IsReady()) { -#else - LL_RCC_LSI_Enable(); - while (!LL_RCC_LSI_IsReady()) { -#endif /* CONFIG_SOC_SERIES_STM32WBX */ - /* Wait for LSI ready */ - } - - LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSI); - -#else /* CONFIG_STM32_LPTIM_CLOCK_LSI */ -#if defined(LL_APB1_GRP1_PERIPH_PWR) - /* Enable the power interface clock */ - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); -#endif /* LL_APB1_GRP1_PERIPH_PWR */ - - /* enable backup domain */ - LL_PWR_EnableBkUpAccess(); - - /* enable LSE clock */ - LL_RCC_LSE_DisableBypass(); - LL_RCC_LSE_Enable(); - while (!LL_RCC_LSE_IsReady()) { - /* Wait for LSE ready */ - } -#ifdef RCC_BDCR_LSESYSEN - LL_RCC_LSE_EnablePropagation(); -#endif /* RCC_BDCR_LSESYSEN */ - LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE); - -#endif /* CONFIG_STM32_LPTIM_CLOCK_LSI */ - - /* Clear the event flag and possible pending interrupt */ - IRQ_CONNECT(DT_IRQN(DT_NODELABEL(lptim1)), - DT_IRQ(DT_NODELABEL(lptim1), priority), - lptim_irq_handler, 0, 0); - irq_enable(DT_IRQN(DT_NODELABEL(lptim1))); - -#ifdef CONFIG_SOC_SERIES_STM32WLX - /* Enable the LPTIM1 wakeup EXTI line */ - LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_29); -#endif - - /* configure the LPTIM1 counter */ - LL_LPTIM_SetClockSource(LPTIM1, LL_LPTIM_CLK_SOURCE_INTERNAL); - /* configure the LPTIM1 prescaler with 1 */ - LL_LPTIM_SetPrescaler(LPTIM1, LL_LPTIM_PRESCALER_DIV1); -#ifdef CONFIG_SOC_SERIES_STM32U5X - LL_LPTIM_OC_SetPolarity(LPTIM1, LL_LPTIM_CHANNEL_CH1, - LL_LPTIM_OUTPUT_POLARITY_REGULAR); -#else - LL_LPTIM_SetPolarity(LPTIM1, LL_LPTIM_OUTPUT_POLARITY_REGULAR); -#endif - LL_LPTIM_SetUpdateMode(LPTIM1, LL_LPTIM_UPDATE_MODE_IMMEDIATE); - LL_LPTIM_SetCounterMode(LPTIM1, LL_LPTIM_COUNTER_MODE_INTERNAL); - LL_LPTIM_DisableTimeout(LPTIM1); - /* counting start is initiated by software */ - LL_LPTIM_TrigSw(LPTIM1); - -#ifdef CONFIG_SOC_SERIES_STM32U5X - /* Enable the LPTIM1 before proceeding with configuration */ - LL_LPTIM_Enable(LPTIM1); - - LL_LPTIM_DisableIT_CC1(LPTIM1); - while (LL_LPTIM_IsActiveFlag_DIEROK(LPTIM1) == 0) { - } - LL_LPTIM_ClearFlag_DIEROK(LPTIM1); - LL_LPTIM_ClearFLAG_CC1(LPTIM1); -#else - /* LPTIM1 interrupt set-up before enabling */ - /* no Compare match Interrupt */ - LL_LPTIM_DisableIT_CMPM(LPTIM1); - LL_LPTIM_ClearFLAG_CMPM(LPTIM1); -#endif - - /* Autoreload match Interrupt */ - LL_LPTIM_EnableIT_ARRM(LPTIM1); -#ifdef CONFIG_SOC_SERIES_STM32U5X - while (LL_LPTIM_IsActiveFlag_DIEROK(LPTIM1) == 0) { - } - LL_LPTIM_ClearFlag_DIEROK(LPTIM1); -#endif - LL_LPTIM_ClearFLAG_ARRM(LPTIM1); - /* ARROK bit validates the write operation to ARR register */ - LL_LPTIM_ClearFlag_ARROK(LPTIM1); - - accumulated_lptim_cnt = 0; - -#ifndef CONFIG_SOC_SERIES_STM32U5X - /* Enable the LPTIM1 counter */ - LL_LPTIM_Enable(LPTIM1); -#endif - - /* Set the Autoreload value once the timer is enabled */ - if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - /* LPTIM1 is triggered on a LPTIM_TIMEBASE period */ - LL_LPTIM_SetAutoReload(LPTIM1, LPTIM_TIMEBASE); - - } else { - /* LPTIM1 is triggered on a Tick period */ - LL_LPTIM_SetAutoReload(LPTIM1, COUNT_PER_TICK - 1); - } - - /* Start the LPTIM counter in continuous mode */ - LL_LPTIM_StartCounter(LPTIM1, LL_LPTIM_OPERATING_MODE_CONTINUOUS); - -#ifdef CONFIG_DEBUG - /* stop LPTIM1 during DEBUG */ -#if defined(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP) - LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP); -#elif defined(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP) - LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP); -#endif - -#endif - return 0; -} - static inline uint32_t z_clock_lptim_getcounter(void) { uint32_t lp_time; @@ -374,3 +240,141 @@ uint32_t sys_clock_cycle_get_32(void) /* convert in hw cycles (keeping 32bit value) */ return (uint32_t)(ret); } + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* enable LPTIM clock source */ +#if defined(LL_APB1_GRP1_PERIPH_LPTIM1) + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPTIM1); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_LPTIM1); +#elif defined(LL_APB3_GRP1_PERIPH_LPTIM1) + LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_LPTIM1); + LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_LPTIM1AMEN); +#endif + +#if defined(CONFIG_STM32_LPTIM_CLOCK_LSI) + /* enable LSI clock */ +#ifdef CONFIG_SOC_SERIES_STM32WBX + LL_RCC_LSI1_Enable(); + while (!LL_RCC_LSI1_IsReady()) { +#else + LL_RCC_LSI_Enable(); + while (!LL_RCC_LSI_IsReady()) { +#endif /* CONFIG_SOC_SERIES_STM32WBX */ + /* Wait for LSI ready */ + } + + LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSI); + +#else /* CONFIG_STM32_LPTIM_CLOCK_LSI */ +#if defined(LL_APB1_GRP1_PERIPH_PWR) + /* Enable the power interface clock */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); +#endif /* LL_APB1_GRP1_PERIPH_PWR */ + + /* enable backup domain */ + LL_PWR_EnableBkUpAccess(); + + /* enable LSE clock */ + LL_RCC_LSE_DisableBypass(); + LL_RCC_LSE_Enable(); + while (!LL_RCC_LSE_IsReady()) { + /* Wait for LSE ready */ + } +#ifdef RCC_BDCR_LSESYSEN + LL_RCC_LSE_EnablePropagation(); +#endif /* RCC_BDCR_LSESYSEN */ + LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE); + +#endif /* CONFIG_STM32_LPTIM_CLOCK_LSI */ + + /* Clear the event flag and possible pending interrupt */ + IRQ_CONNECT(DT_IRQN(DT_NODELABEL(lptim1)), + DT_IRQ(DT_NODELABEL(lptim1), priority), + lptim_irq_handler, 0, 0); + irq_enable(DT_IRQN(DT_NODELABEL(lptim1))); + +#ifdef CONFIG_SOC_SERIES_STM32WLX + /* Enable the LPTIM1 wakeup EXTI line */ + LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_29); +#endif + + /* configure the LPTIM1 counter */ + LL_LPTIM_SetClockSource(LPTIM1, LL_LPTIM_CLK_SOURCE_INTERNAL); + /* configure the LPTIM1 prescaler with 1 */ + LL_LPTIM_SetPrescaler(LPTIM1, LL_LPTIM_PRESCALER_DIV1); +#ifdef CONFIG_SOC_SERIES_STM32U5X + LL_LPTIM_OC_SetPolarity(LPTIM1, LL_LPTIM_CHANNEL_CH1, + LL_LPTIM_OUTPUT_POLARITY_REGULAR); +#else + LL_LPTIM_SetPolarity(LPTIM1, LL_LPTIM_OUTPUT_POLARITY_REGULAR); +#endif + LL_LPTIM_SetUpdateMode(LPTIM1, LL_LPTIM_UPDATE_MODE_IMMEDIATE); + LL_LPTIM_SetCounterMode(LPTIM1, LL_LPTIM_COUNTER_MODE_INTERNAL); + LL_LPTIM_DisableTimeout(LPTIM1); + /* counting start is initiated by software */ + LL_LPTIM_TrigSw(LPTIM1); + +#ifdef CONFIG_SOC_SERIES_STM32U5X + /* Enable the LPTIM1 before proceeding with configuration */ + LL_LPTIM_Enable(LPTIM1); + + LL_LPTIM_DisableIT_CC1(LPTIM1); + while (LL_LPTIM_IsActiveFlag_DIEROK(LPTIM1) == 0) { + } + LL_LPTIM_ClearFlag_DIEROK(LPTIM1); + LL_LPTIM_ClearFLAG_CC1(LPTIM1); +#else + /* LPTIM1 interrupt set-up before enabling */ + /* no Compare match Interrupt */ + LL_LPTIM_DisableIT_CMPM(LPTIM1); + LL_LPTIM_ClearFLAG_CMPM(LPTIM1); +#endif + + /* Autoreload match Interrupt */ + LL_LPTIM_EnableIT_ARRM(LPTIM1); +#ifdef CONFIG_SOC_SERIES_STM32U5X + while (LL_LPTIM_IsActiveFlag_DIEROK(LPTIM1) == 0) { + } + LL_LPTIM_ClearFlag_DIEROK(LPTIM1); +#endif + LL_LPTIM_ClearFLAG_ARRM(LPTIM1); + /* ARROK bit validates the write operation to ARR register */ + LL_LPTIM_ClearFlag_ARROK(LPTIM1); + + accumulated_lptim_cnt = 0; + +#ifndef CONFIG_SOC_SERIES_STM32U5X + /* Enable the LPTIM1 counter */ + LL_LPTIM_Enable(LPTIM1); +#endif + + /* Set the Autoreload value once the timer is enabled */ + if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + /* LPTIM1 is triggered on a LPTIM_TIMEBASE period */ + LL_LPTIM_SetAutoReload(LPTIM1, LPTIM_TIMEBASE); + + } else { + /* LPTIM1 is triggered on a Tick period */ + LL_LPTIM_SetAutoReload(LPTIM1, COUNT_PER_TICK - 1); + } + + /* Start the LPTIM counter in continuous mode */ + LL_LPTIM_StartCounter(LPTIM1, LL_LPTIM_OPERATING_MODE_CONTINUOUS); + +#ifdef CONFIG_DEBUG + /* stop LPTIM1 during DEBUG */ +#if defined(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP) + LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP); +#elif defined(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP) + LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP); +#endif + +#endif + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/sys_clock_init.c b/drivers/timer/sys_clock_init.c index c280daabe65..f44dc7299f4 100644 --- a/drivers/timer/sys_clock_init.c +++ b/drivers/timer/sys_clock_init.c @@ -23,13 +23,6 @@ void __weak sys_clock_isr(void *arg) __ASSERT_NO_MSG(false); } -int __weak sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - return 0; -} - void __weak sys_clock_set_timeout(int32_t ticks, bool idle) { } @@ -41,6 +34,3 @@ void __weak sys_clock_idle_exit(void) void __weak sys_clock_disable(void) { } - -SYS_DEVICE_DEFINE("sys_clock", sys_clock_driver_init, - PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/xlnx_psttc_timer.c b/drivers/timer/xlnx_psttc_timer.c index c1e6ca38654..0cc4fc43db3 100644 --- a/drivers/timer/xlnx_psttc_timer.c +++ b/drivers/timer/xlnx_psttc_timer.c @@ -7,6 +7,7 @@ #define DT_DRV_COMPAT xlnx_ttcps +#include #include #include #include "xlnx_psttc_timer_priv.h" @@ -96,7 +97,50 @@ static void ttc_isr(const void *arg) sys_clock_announce(ticks); } -int sys_clock_driver_init(const struct device *dev) +void sys_clock_set_timeout(int32_t ticks, bool idle) +{ +#ifdef CONFIG_TICKLESS_KERNEL + uint32_t cycles; + uint32_t next_cycles; + + /* Read counter value */ + cycles = read_count(); + + /* Calculate timeout counter value */ + if (ticks == K_TICKS_FOREVER) { + next_cycles = cycles + CYCLES_NEXT_MAX; + } else { + next_cycles = cycles + ((uint32_t)ticks * CYCLES_PER_TICK); + } + + /* Set match value for the next interrupt */ + update_match(cycles, next_cycles); +#endif +} + +uint32_t sys_clock_elapsed(void) +{ +#ifdef CONFIG_TICKLESS_KERNEL + uint32_t cycles; + + /* Read counter value */ + cycles = read_count(); + + /* Return the number of ticks since last announcement */ + return (cycles - last_cycles) / CYCLES_PER_TICK; +#else + /* Always return 0 for tickful operation */ + return 0; +#endif +} + +uint32_t sys_clock_cycle_get_32(void) +{ + /* Return the current counter value */ + return read_count(); +} + +static int sys_clock_driver_init(const struct device *dev) { uint32_t reg_val; ARG_UNUSED(dev); @@ -153,45 +197,5 @@ int sys_clock_driver_init(const struct device *dev) return 0; } -void sys_clock_set_timeout(int32_t ticks, bool idle) -{ -#ifdef CONFIG_TICKLESS_KERNEL - uint32_t cycles; - uint32_t next_cycles; - - /* Read counter value */ - cycles = read_count(); - - /* Calculate timeout counter value */ - if (ticks == K_TICKS_FOREVER) { - next_cycles = cycles + CYCLES_NEXT_MAX; - } else { - next_cycles = cycles + ((uint32_t)ticks * CYCLES_PER_TICK); - } - - /* Set match value for the next interrupt */ - update_match(cycles, next_cycles); -#endif -} - -uint32_t sys_clock_elapsed(void) -{ -#ifdef CONFIG_TICKLESS_KERNEL - uint32_t cycles; - - /* Read counter value */ - cycles = read_count(); - - /* Return the number of ticks since last announcement */ - return (cycles - last_cycles) / CYCLES_PER_TICK; -#else - /* Always return 0 for tickful operation */ - return 0; -#endif -} - -uint32_t sys_clock_cycle_get_32(void) -{ - /* Return the current counter value */ - return read_count(); -} +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/xtensa_sys_timer.c b/drivers/timer/xtensa_sys_timer.c index b7e5304bcc2..752f93a3d52 100644 --- a/drivers/timer/xtensa_sys_timer.c +++ b/drivers/timer/xtensa_sys_timer.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -56,16 +57,6 @@ static void ccompare_isr(const void *arg) sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? dticks : 1); } -int sys_clock_driver_init(const struct device *dev) -{ - ARG_UNUSED(dev); - - IRQ_CONNECT(TIMER_IRQ, 0, ccompare_isr, 0, 0); - set_ccompare(ccount() + CYC_PER_TICK); - irq_enable(TIMER_IRQ); - return 0; -} - void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); @@ -122,3 +113,16 @@ void smp_timer_init(void) irq_enable(TIMER_IRQ); } #endif + +static int sys_clock_driver_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + IRQ_CONNECT(TIMER_IRQ, 0, ccompare_isr, 0, 0); + set_ccompare(ccount() + CYC_PER_TICK); + irq_enable(TIMER_IRQ); + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/include/drivers/timer/system_timer.h b/include/drivers/timer/system_timer.h index 7fda00f4219..e875e63892e 100644 --- a/include/drivers/timer/system_timer.h +++ b/include/drivers/timer/system_timer.h @@ -16,8 +16,7 @@ #define ZEPHYR_INCLUDE_DRIVERS_SYSTEM_TIMER_H_ #include -#include -#include +#include #ifdef __cplusplus extern "C" { @@ -29,15 +28,6 @@ extern "C" { * @{ */ -/** - * @brief Initialize system clock driver - * - * The system clock is a Zephyr device created globally. This is its - * initialization callback. It is a weak symbol that will be - * implemented as a noop if undefined in the clock driver. - */ -extern int sys_clock_driver_init(const struct device *dev); - /** * @brief Set system clock timeout *