From 5720d9dad485e95b81ac251af3a7dfb074980e1f Mon Sep 17 00:00:00 2001 From: Scott Worley Date: Tue, 1 Jul 2025 15:09:59 -0400 Subject: [PATCH] drivers: timer: microchip: xec: Microchip MEC one kernel timer driver We want to simplify the maintenance burden and confusion of having more than one driver for the same kernel timer peripheral used on all Microchip MEC parts. The XEC version of the driver was converted register definitions in the driver. Register access is performed using Zephyr sys_read/write architecture specific inline routines. Driver DT YAML was updated to use phandle for the 32-bit basic timer used for ARCH_HAS_CUSTOM_BUSY_WAIT support, basic timer max value property, and GIRQ interrtup aggregator hardware information. SoC part Kconfigs, chip level/board level DTSI updated to use the unified driver. Signed-off-by: Scott Worley --- .../mec15xxevb_assy6853.dts | 4 - .../mec172xevb_assy6906.dts | 4 - .../mec172xmodular_assy6930.dts | 4 - .../mec_assy6941/mec_assy6941_mec1743_qlj.dts | 7 - .../mec_assy6941/mec_assy6941_mec1743_qsz.dts | 7 - .../mec_assy6941/mec_assy6941_mec1753_qlj.dts | 7 - .../mec_assy6941/mec_assy6941_mec1753_qsz.dts | 7 - drivers/timer/CMakeLists.txt | 1 - drivers/timer/Kconfig | 1 - drivers/timer/Kconfig.mec5 | 17 - drivers/timer/mchp_mec5_ktimer.c | 405 ------------------ drivers/timer/mchp_xec_rtos_timer.c | 202 ++++----- dts/arm/microchip/mec/mec1501hsz.dtsi | 1 + dts/arm/microchip/mec/mec172x_common.dtsi | 1 + dts/arm/microchip/mec/mec5.dtsi | 10 +- .../microchip,dmec-ecia-girq.yaml | 23 + dts/bindings/timer/microchip,mec5-ktimer.yaml | 29 -- .../timer/microchip,xec-basic-timer.yaml | 35 ++ .../timer/microchip,xec-rtos-timer.yaml | 11 +- .../mec/mec174x/Kconfig.defconfig.series | 11 +- .../mec/mec175x/Kconfig.defconfig.series | 11 +- .../mec/mech172x/Kconfig.defconfig.series | 11 +- 22 files changed, 191 insertions(+), 618 deletions(-) delete mode 100644 drivers/timer/Kconfig.mec5 delete mode 100644 drivers/timer/mchp_mec5_ktimer.c create mode 100644 dts/bindings/interrupt-controller/microchip,dmec-ecia-girq.yaml delete mode 100644 dts/bindings/timer/microchip,mec5-ktimer.yaml create mode 100644 dts/bindings/timer/microchip,xec-basic-timer.yaml diff --git a/boards/microchip/mec15xxevb_assy6853/mec15xxevb_assy6853.dts b/boards/microchip/mec15xxevb_assy6853/mec15xxevb_assy6853.dts index fbc1aa677af0..c7e432931018 100644 --- a/boards/microchip/mec15xxevb_assy6853/mec15xxevb_assy6853.dts +++ b/boards/microchip/mec15xxevb_assy6853/mec15xxevb_assy6853.dts @@ -131,10 +131,6 @@ pinctrl-names = "default"; }; -&timer5 { - status = "okay"; -}; - &ps2_0 { status = "okay"; pinctrl-0 = <&ps2_clk0b_gpio007 &ps2_dat0b_gpio010>; diff --git a/boards/microchip/mec172xevb_assy6906/mec172xevb_assy6906.dts b/boards/microchip/mec172xevb_assy6906/mec172xevb_assy6906.dts index 97bbc8efdacc..15019a36e852 100644 --- a/boards/microchip/mec172xevb_assy6906/mec172xevb_assy6906.dts +++ b/boards/microchip/mec172xevb_assy6906/mec172xevb_assy6906.dts @@ -285,7 +285,3 @@ pinctrl-1 = <&ps2_clk0a_gpio114_sleep &ps2_dat0a_gpio115_sleep>; pinctrl-names = "default", "sleep"; }; - -&timer5 { - status = "okay"; -}; diff --git a/boards/microchip/mec172xmodular_assy6930/mec172xmodular_assy6930.dts b/boards/microchip/mec172xmodular_assy6930/mec172xmodular_assy6930.dts index 79c95ef63b8a..253d799f9234 100644 --- a/boards/microchip/mec172xmodular_assy6930/mec172xmodular_assy6930.dts +++ b/boards/microchip/mec172xmodular_assy6930/mec172xmodular_assy6930.dts @@ -262,7 +262,3 @@ pinctrl-0 = <&ps2_clk0a_gpio114 &ps2_dat0a_gpio115>; pinctrl-names = "default"; }; - -&timer5 { - status = "okay"; -}; diff --git a/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qlj.dts b/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qlj.dts index 719cf8115930..0b885f29dc0a 100644 --- a/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qlj.dts +++ b/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qlj.dts @@ -17,7 +17,6 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,console = &uart1; - rtimer-busy-wait-timer = &timer5; }; power-states { @@ -48,12 +47,6 @@ /* Enable MCHP kernel timer driver using 32KHz RTOS timer and 1MHz basic timer */ &rtimer { - compatible = "microchip,mec5-ktimer"; - status = "okay"; -}; - -/* We chose 32-bit basic timer 5 for use by ktimer */ -&timer5 { status = "okay"; }; diff --git a/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qsz.dts b/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qsz.dts index 83f79dca5521..b395ec21bc40 100644 --- a/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qsz.dts +++ b/boards/microchip/mec_assy6941/mec_assy6941_mec1743_qsz.dts @@ -17,7 +17,6 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,console = &uart1; - rtimer-busy-wait-timer = &timer5; }; power-states { @@ -48,12 +47,6 @@ /* Enable MCHP kernel timer driver using 32KHz RTOS timer and 1MHz basic timer */ &rtimer { - compatible = "microchip,mec5-ktimer"; - status = "okay"; -}; - -/* We chose 32-bit basic timer 5 for use by ktimer */ -&timer5 { status = "okay"; }; diff --git a/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qlj.dts b/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qlj.dts index 52e655e828f1..724088b2d482 100644 --- a/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qlj.dts +++ b/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qlj.dts @@ -17,7 +17,6 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,console = &uart1; - rtimer-busy-wait-timer = &timer5; }; power-states { @@ -48,12 +47,6 @@ /* Enable MCHP kernel timer driver using 32KHz RTOS timer and 1MHz basic timer */ &rtimer { - compatible = "microchip,mec5-ktimer"; - status = "okay"; -}; - -/* We chose 32-bit basic timer 5 for use by ktimer */ -&timer5 { status = "okay"; }; diff --git a/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qsz.dts b/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qsz.dts index fc8756cda33a..ae51d2028555 100644 --- a/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qsz.dts +++ b/boards/microchip/mec_assy6941/mec_assy6941_mec1753_qsz.dts @@ -17,7 +17,6 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,console = &uart1; - rtimer-busy-wait-timer = &timer5; }; power-states { @@ -48,12 +47,6 @@ /* Enable MCHP kernel timer driver using 32KHz RTOS timer and 1MHz basic timer */ &rtimer { - compatible = "microchip,mec5-ktimer"; - status = "okay"; -}; - -/* We chose 32-bit basic timer 5 for use by ktimer */ -&timer5 { status = "okay"; }; diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index 3c488da9a3e7..a354de5e35e3 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -21,7 +21,6 @@ zephyr_library_sources_ifdef(CONFIG_ITE_IT51XXX_TIMER ite_it51xxx_timer.c) zephyr_library_sources_ifdef(CONFIG_ITE_IT8XXX2_TIMER ite_it8xxx2_timer.c) zephyr_library_sources_ifdef(CONFIG_LEON_GPTIMER leon_gptimer.c) zephyr_library_sources_ifdef(CONFIG_LITEX_TIMER litex_timer.c) -zephyr_library_sources_ifdef(CONFIG_MCHP_MEC5_KTIMER mchp_mec5_ktimer.c) zephyr_library_sources_ifdef(CONFIG_MCHP_XEC_RTOS_TIMER mchp_xec_rtos_timer.c) zephyr_library_sources_ifdef(CONFIG_MCHP_SAM_PIT64B_TIMER mchp_sam_pit64b_timer.c) zephyr_library_sources_ifdef(CONFIG_MCUX_LPTMR_TIMER mcux_lptmr_timer.c) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index c154370c4563..1cb165f329ff 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -83,7 +83,6 @@ source "drivers/timer/Kconfig.mchp_sam" source "drivers/timer/Kconfig.mcux_gpt" source "drivers/timer/Kconfig.mcux_lptmr" source "drivers/timer/Kconfig.mcux_os" -source "drivers/timer/Kconfig.mec5" source "drivers/timer/Kconfig.mips_cp0" source "drivers/timer/Kconfig.native_sim" source "drivers/timer/Kconfig.npcx_itim" diff --git a/drivers/timer/Kconfig.mec5 b/drivers/timer/Kconfig.mec5 deleted file mode 100644 index ccc466d2f3b0..000000000000 --- a/drivers/timer/Kconfig.mec5 +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2024 Microchip Technology Inc. -# SPDX-License-Identifier: Apache-2.0 - -config MCHP_MEC5_KTIMER - bool "Microchip MEC5 HAL kernel timer" - default y - depends on DT_HAS_MICROCHIP_MEC5_KTIMER_ENABLED - select TICKLESS_CAPABLE - select SYSTEM_TIMER_HAS_DISABLE_SUPPORT - select ARCH_HAS_CUSTOM_BUSY_WAIT - help - This module implements a kernel timer device driver for the - Microchip MEC5 SoC. It makes use of two hardware timers. - The 32-bit 32 KHz based RTOS timer which is operational in - full power and deep sleep. Basic timer 5 is a 48 MHz based - 32-bit down counter with frequency divider used for the - custom busy wait kernel API. diff --git a/drivers/timer/mchp_mec5_ktimer.c b/drivers/timer/mchp_mec5_ktimer.c deleted file mode 100644 index 704141892a61..000000000000 --- a/drivers/timer/mchp_mec5_ktimer.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (c) 2024 Microchip Technology Incorporated - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT microchip_mec5_ktimer - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "MCHP MEC5 ktimer doesn't support SMP"); -BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768, - "MCHP MEC5 ktimer HW frequency is fixed at 32768"); - -#ifndef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT -BUILD_ASSERT(0, "MCHP MEC5 ktimer requires ARCH_HAS_CUSTOM_BUSY_WAIT"); -#endif - -#ifdef CONFIG_SOC_MEC_DEBUG_AND_TRACING -#define RTIMER_START_VAL MEC_RTIMER_START_EXT_HALT -#else -#define RTIMER_START_VAL MEC_RTIMER_START -#endif - -/* - * Overview: - * - * This driver enables the Microchip XEC 32KHz based RTOS timer as the Zephyr - * system timer. It supports both legacy ("tickful") mode as well as - * TICKLESS_KERNEL. The XEC RTOS timer is a down counter with a fixed - * frequency of 32768 Hz. The driver is based upon the Intel local APIC - * timer driver. - * Configuration: - * - * CONFIG_MCHP_XEC_RTOS_TIMER=y - * - * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC= must be set to 32768. - * - * To reduce truncation errors from accumulating due to conversion - * to/from time, ticks, and HW cycles set ticks per second equal to - * the frequency. With tickless kernel mode enabled the kernel will not - * program a periodic timer at this fast rate. - * CONFIG_SYS_CLOCK_TICKS_PER_SEC=32768 - */ - -#define CYCLES_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) - -/* Mask off bits[31:28] of 32-bit count */ -#define RTIMER_MAX 0x0fffffffu -#define RTIMER_COUNT_MASK 0x0fffffffu -#define RTIMER_STOPPED 0xf0000000u - -/* Adjust cycle count programmed into timer for HW restart latency */ -#define RTIMER_ADJUST_LIMIT 2 -#define RTIMER_ADJUST_CYCLES 1 - -/* max number of ticks we can load into the timer in one shot */ -#define MAX_TICKS (RTIMER_MAX / CYCLES_PER_TICK) - -#define RTIMER_NODE_ID DT_INST(0, DT_DRV_COMPAT) -#define RTIMER_NVIC_NO DT_INST_IRQN(0) -#define RTIMER_NVIC_PRIO DT_INST_IRQ(0, priority) - -static struct mec_rtmr_regs *const rtimer = (struct mec_rtmr_regs *)DT_INST_REG_ADDR(0); - -#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT -#define BTIMER_NODE_ID DT_CHOSEN(rtimer_busy_wait_timer) -#define MEC5_BTIMER_FDIV (MEC5_BTIMER_MAX_FREQ_HZ / 1000000u) - -static struct mec_btmr_regs *const btimer = (struct mec_btmr_regs *)DT_REG_ADDR(BTIMER_NODE_ID); -#endif - -/* - * The spinlock protects all access to the RTIMER registers, as well as - * 'total_cycles', 'last_announcement', and 'cached_icr'. - * - * One important invariant that must be observed: `total_cycles` + `cached_icr` - * is always an integral multiple of CYCLE_PER_TICK; this is, timer interrupts - * are only ever scheduled to occur at tick boundaries. - */ - -static struct k_spinlock lock; -static uint32_t total_cycles; -static uint32_t cached_icr = CYCLES_PER_TICK; - -/* - * Read the RTOS timer counter handling the case where the timer - * has been reloaded within 1 32KHz clock of reading its count register. - * The RTOS timer hardware must synchronize the write to its control register - * on the AHB clock domain with the 32KHz clock domain of its internal logic. - * This synchronization can take from nearly 0 time up to 1 32KHz clock as it - * depends upon which 48MHz AHB clock with a 32KHz period the register write - * was on. We detect the timer is in the load state by checking the read-only - * count register and the START bit in the control register. If count register - * is 0 and the START bit is set then the timer has been started and is in the - * process of moving the preload register value into the count register. - */ -static inline uint32_t rtimer_count(void) -{ - uint32_t ccr = mec_hal_rtimer_count(rtimer); - - if ((ccr == 0) && mec_hal_rtimer_is_started(rtimer)) { - ccr = cached_icr; - } - - return ccr; -} - -#ifdef CONFIG_TICKLESS_KERNEL - -static uint32_t last_announcement; /* last time we called sys_clock_announce() */ - -/* - * Request a timeout n Zephyr ticks in the future from now. - * Requested number of ticks in the future of n <= 1 means the kernel wants - * the tick announced as soon as possible, ideally no more than one tick - * in the future. - * - * Per comment below we don't clear RTMR pending interrupt. - * RTMR counter register is read-only and is loaded from the preload - * register by a 0->1 transition of the control register start bit. - * Writing a new value to preload only takes effect once the count - * register reaches 0. - */ -void sys_clock_set_timeout(int32_t n, bool idle) -{ - ARG_UNUSED(idle); - - uint32_t ccr, temp; - int full_ticks; /* number of complete ticks we'll wait */ - uint32_t full_cycles; /* full_ticks represented as cycles */ - uint32_t partial_cycles; /* number of cycles to first tick boundary */ - - if (idle && (n == K_TICKS_FOREVER)) { - /* - * We are not in a locked section. Are writes to two - * global objects safe from pre-emption? - */ - mec_hal_rtimer_stop(rtimer); - cached_icr = RTIMER_STOPPED; - return; - } - - if (n < 1) { - full_ticks = 0; - } else if ((n == K_TICKS_FOREVER) || (n > MAX_TICKS)) { - full_ticks = MAX_TICKS - 1; - } else { - full_ticks = n - 1; - } - - full_cycles = full_ticks * CYCLES_PER_TICK; - - k_spinlock_key_t key = k_spin_lock(&lock); - - ccr = rtimer_count(); - - /* turn off to clear any pending interrupt status */ - mec_hal_rtimer_stop(rtimer); - mec_hal_rtimer_status_clear_all(rtimer); - NVIC_ClearPendingIRQ(RTIMER_NVIC_NO); - - temp = total_cycles; - temp += (cached_icr - ccr); - temp &= RTIMER_COUNT_MASK; - total_cycles = temp; - - partial_cycles = CYCLES_PER_TICK - (total_cycles % CYCLES_PER_TICK); - cached_icr = full_cycles + partial_cycles; - /* adjust for up to one 32KHz cycle startup time */ - temp = cached_icr; - if (temp > RTIMER_ADJUST_LIMIT) { - temp -= RTIMER_ADJUST_CYCLES; - } - - mec_hal_rtimer_stop_and_load(rtimer, temp, RTIMER_START_VAL); - - k_spin_unlock(&lock, key); -} - -/* - * Return the number of Zephyr ticks elapsed from last call to - * sys_clock_announce in the ISR. The caller casts uint32_t to int32_t. - * We must make sure bit[31] is 0 in the return value. - */ -uint32_t sys_clock_elapsed(void) -{ - uint32_t ccr; - uint32_t ticks; - int32_t elapsed; - - k_spinlock_key_t key = k_spin_lock(&lock); - - ccr = rtimer_count(); - - /* It may not look efficient but the compiler does a good job */ - elapsed = (int32_t)total_cycles - (int32_t)last_announcement; - if (elapsed < 0) { - elapsed = -1 * elapsed; - } - ticks = (uint32_t)elapsed; - ticks += cached_icr - ccr; - ticks /= CYCLES_PER_TICK; - ticks &= RTIMER_COUNT_MASK; - - k_spin_unlock(&lock, key); - - return ticks; -} - -static void mec5_ktimer_isr(const void *arg) -{ - ARG_UNUSED(arg); - - uint32_t cycles; - int32_t ticks; - - k_spinlock_key_t key = k_spin_lock(&lock); - - mec_hal_rtimer_status_clear_all(rtimer); - - /* Restart the timer as early as possible to minimize drift... */ - mec_hal_rtimer_stop_and_load(rtimer, MAX_TICKS * CYCLES_PER_TICK, RTIMER_START_VAL); - - cycles = cached_icr; - cached_icr = MAX_TICKS * CYCLES_PER_TICK; - - total_cycles += cycles; - total_cycles &= RTIMER_COUNT_MASK; - - /* handle wrap by using (power of 2) - 1 mask */ - ticks = total_cycles - last_announcement; - ticks &= RTIMER_COUNT_MASK; - ticks /= CYCLES_PER_TICK; - - last_announcement = total_cycles; - - k_spin_unlock(&lock, key); - sys_clock_announce(ticks); -} - -#else -/* Non-tickless kernel build. */ -static void mec5_ktimer_isr(const void *arg) -{ - ARG_UNUSED(arg); - - k_spinlock_key_t key = k_spin_lock(&lock); - - mec_hal_rtimer_status_clear_all(rtimer); - - /* Restart the timer as early as possible to minimize drift... */ - mec_hal_rtimer_stop_and_load(rtimer, cached_icr, RTIMER_START_VAL); - - uint32_t temp = total_cycles + CYCLES_PER_TICK; - - total_cycles = temp & RTIMER_COUNT_MASK; - k_spin_unlock(&lock, key); - - sys_clock_announce(1); -} - -uint32_t sys_clock_elapsed(void) -{ - return 0U; -} -#endif /* CONFIG_TICKLESS_KERNEL */ - -/* - * Warning RTOS timer resolution is 30.5 us. - * This is called by two code paths: - * 1. Kernel call to k_cycle_get_32() -> arch_k_cycle_get_32() -> here. - * The kernel is casting return to (int) and using it uncasted in math - * expressions with int types. Expression result is stored in an int. - * 2. If CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT is not defined then - * z_impl_k_busy_wait calls here. This code path uses the value as uint32_t. - * - */ -uint32_t sys_clock_cycle_get_32(void) -{ - uint32_t ret; - uint32_t ccr; - - k_spinlock_key_t key = k_spin_lock(&lock); - - ccr = rtimer_count(); - ret = (total_cycles + (cached_icr - ccr)) & RTIMER_COUNT_MASK; - - k_spin_unlock(&lock, key); - - return ret; -} - -void sys_clock_idle_exit(void) -{ - if (cached_icr == RTIMER_STOPPED) { - cached_icr = CYCLES_PER_TICK; - mec_hal_rtimer_stop_and_load(rtimer, cached_icr, RTIMER_START_VAL); - } -} - -void sys_clock_disable(void) -{ - mec_hal_rtimer_stop(rtimer); -} - -#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT -/* Custom kernel busy wait API implementation using a 48MHz based - * 32-bit basic timer divided down to 1 MHz. Basic timer configured - * for count up, auto-reload, and no interrupt mode. - */ -void arch_busy_wait(uint32_t usec_to_wait) -{ - if (usec_to_wait == 0) { - return; - } - - uint32_t start = mec_hal_btimer_count(btimer); - - for (;;) { - uint32_t curr = mec_hal_btimer_count(btimer); - - if ((curr - start) >= usec_to_wait) { - break; - } - } -} - -/* k_busy_wait parameter is the number of microseconds to wait. - * Configure basic timer for 1 MHz (1 us tick) operation. - */ -static int config_custom_busy_wait(void) -{ - uint32_t bflags = - (BIT(MEC5_BTIMER_CFG_FLAG_START_POS) | BIT(MEC5_BTIMER_CFG_FLAG_AUTO_RELOAD_POS) | - BIT(MEC5_BTIMER_CFG_FLAG_COUNT_UP_POS)); - uint32_t count = 0; - - mec_hal_btimer_init(btimer, MEC5_BTIMER_FDIV, count, bflags); - - return 0; -} - -void soc_ktimer_pm_entry(bool is_deep_sleep) -{ - if (is_deep_sleep) { - mec_hal_btimer_disable(btimer); - } -} - -void soc_ktimer_pm_exit(bool is_deep_sleep) -{ - if (is_deep_sleep) { - mec_hal_btimer_enable(btimer); - } -} -#else -void soc_ktimer_pm_entry(void) -{ -} -void soc_ktimer_pm_exit(void) -{ -} -#endif /* CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT */ - -static int sys_clock_driver_init(void) -{ - uint32_t rtmr_cfg = BIT(MEC_RTMR_CFG_EN_POS) | BIT(MEC_RTMR_CFG_IEN_POS); - - if (IS_ENABLED(CONFIG_SOC_MEC_DEBUG_AND_TRACING)) { - rtmr_cfg |= BIT(MEC_RTMR_CFG_DBG_HALT_POS); - } - -#ifdef CONFIG_TICKLESS_KERNEL - cached_icr = MAX_TICKS; -#endif - - mec_hal_rtimer_init(rtimer, rtmr_cfg, cached_icr); - - IRQ_CONNECT(RTIMER_NVIC_NO, RTIMER_NVIC_PRIO, mec5_ktimer_isr, 0, 0); - irq_enable(RTIMER_NVIC_NO); - -#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT - config_custom_busy_wait(); -#endif - - mec_hal_rtimer_start(rtimer); - while (!mec_hal_rtimer_is_counting(rtimer)) { - ; - } - - 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 b57fee45a399..a913c9814746 100644 --- a/drivers/timer/mchp_xec_rtos_timer.c +++ b/drivers/timer/mchp_xec_rtos_timer.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,14 +20,32 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "XEC RTOS timer doesn't support SMP"); BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768, "XEC RTOS timer HW frequency is fixed at 32768"); +/* Microchip MEC 32-bit RTOS timer runs on the 32 KHz always on clock. + * It is a downcounter with auto-reload capability. + */ +#define TIMER_CNT_OFS 0 /* R/W counter */ +#define TIMER_PRLD_OFS 4u /* R/W preload value */ +#define TIMER_CR_OFS 8u /* R/W control */ +#define TIMER_CR_ACTV_POS 0 /* activate block */ +#define TIMER_CR_ARL_EN_POS 1 /* auto-reload enable */ +#define TIMER_CR_START_POS 2 /* start timer counting */ +#define TIMER_CR_HDBA_POS 3 /* Halt counting if debugger not in reset */ +#define TIMER_CR_HALT_POS 4 /* Halt if written to 1, unhalt by clearing */ + +/* MEC GIRQ */ +#define GIRQ_SIZE 20u /* Each GIRQx is 5 32-bit registers */ +#define GIRQ_SRC_OFS 0 /* R/W1C latched status bits */ +#define GIRQ_ENSET_OFS 4u /* read, write 1 to set enable bit(s) */ +#define GIRQ_RESULT_OFS 8u /* R/O bitwise AND of SRC and ENSET */ +#define GIRQ_ENCLR_OFS 12u /* read, write 1 to clear enable bit(s) */ + #define DEBUG_RTOS_TIMER 0 #if DEBUG_RTOS_TIMER != 0 /* Enable feature to halt timer on JTAG/SWD CPU halt */ -#define TIMER_START_VAL (MCHP_RTMR_CTRL_BLK_EN | MCHP_RTMR_CTRL_START \ - | MCHP_RTMR_CTRL_HW_HALT_EN) +#define TIMER_START_VAL (BIT(TIMER_CR_ACTV_POS) | BIT(TIMER_CR_START_POS) | BIT(TIMER_CR_HALT_POS)) #else -#define TIMER_START_VAL (MCHP_RTMR_CTRL_BLK_EN | MCHP_RTMR_CTRL_START) +#define TIMER_START_VAL (BIT(TIMER_CR_ACTV_POS) | BIT(TIMER_CR_START_POS)) #endif /* @@ -50,46 +69,58 @@ BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768, * CONFIG_SYS_CLOCK_TICKS_PER_SEC=32768 */ -#define CYCLES_PER_TICK \ - (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) +#define CYCLES_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) -#define TIMER_REGS \ - ((struct rtmr_regs *)DT_INST_REG_ADDR(0)) +#define TIMER_BASE (mm_reg_t) DT_INST_REG_ADDR(0) +#define TIMER_GIRQ_NUM DT_INST_PROP_BY_IDX(0, girqs, 0) +#define TIMER_GIRQ_BITPOS DT_INST_PROP_BY_IDX(0, girqs, 1) +/* data sheet GIRQ numbers start at 8 */ +#define TIMER_GIRQ_BASE \ + (mm_reg_t)(DT_REG_ADDR(DT_NODELABEL(ecia)) + (GIRQ_SIZE * (TIMER_GIRQ_NUM - 8u))) -#define ECIA_XEC_REGS \ - ((struct ecia_regs *)DT_REG_ADDR(DT_NODELABEL(ecia))) - -#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT -#define PCR_XEC_REGS \ - ((struct pcr_regs *)DT_REG_ADDR(DT_NODELABEL(pcr))) - -/* - * pcrs property at index 0 is register index into array of 32-bit PCR SLP_EN, - * CLK_REQ, or RST_EN registers. Property at index 1 is the bit position. - */ /*DT_PROP_BY_IDX(DT_NODELABEL(kbc0), girqs, 0)*/ -#define BTMR32_0_PCR_REG_IDX (DT_PROP_BY_IDX(DT_NODELABEL(timer4), pcrs, 0)) -#define BTMR32_0_PCR_BITPOS (DT_PROP_BY_IDX(DT_NODELABEL(timer4), pcrs, 1)) - -#define BTMR32_0_REGS \ - ((struct btmr_regs *)(DT_REG_ADDR(DT_NODELABEL(timer4)))) -#endif +#define TIMER_NVIC_NO DT_INST_IRQN(0) +#define TIMER_NVIC_PRIO DT_INST_IRQ(0, priority) /* Mask off bits[31:28] of 32-bit count */ -#define TIMER_MAX 0x0fffffffu -#define TIMER_COUNT_MASK 0x0fffffffu -#define TIMER_STOPPED 0xf0000000u +#define TIMER_MAX 0x0fffffffu +#define TIMER_COUNT_MASK 0x0fffffffu +#define TIMER_STOPPED 0xf0000000u /* Adjust cycle count programmed into timer for HW restart latency */ -#define TIMER_ADJUST_LIMIT 2 -#define TIMER_ADJUST_CYCLES 1 +#define TIMER_ADJUST_LIMIT 2 +#define TIMER_ADJUST_CYCLES 1 /* max number of ticks we can load into the timer in one shot */ #define MAX_TICKS (TIMER_MAX / CYCLES_PER_TICK) -#define TIMER_GIRQ DT_INST_PROP_BY_IDX(0, girqs, 0) -#define TIMER_GIRQ_POS DT_INST_PROP_BY_IDX(0, girqs, 1) -#define TIMER_NVIC_NO DT_INST_IRQN(0) -#define TIMER_NVIC_PRIO DT_INST_IRQ(0, priority) +#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT +BUILD_ASSERT(DT_INST_NODE_HAS_PROP(0, busy_wait_timer), + "Driver does not not have busy-wait-timer property!"); + +#define BTMR_NODE DT_INST_PHANDLE(0, busy_wait_timer) + +BUILD_ASSERT(DT_PROP(BTMR_NODE, max_value) == UINT32_MAX, "Custom busy wait timer is not 32-bit!"); + +#define BTMR_BASE (mm_reg_t) DT_REG_ADDR(BTMR_NODE) + +#define BTMR_CNT_OFS 0 +#define BTMR_PRLD_OFS 4u +#define BTMR_SR_OFS 8u +#define BTMR_IER_OFS 0xcu +#define BTMR_CR_OFS 0x10u +#define BTMR_CR_ACTV_POS 0 +#define BTMR_CR_CNT_UP_POS 2 +#define BTMR_CR_ARS_POS 3 +#define BTMR_CR_SOFT_RST_POS 4 +#define BTMR_CR_START_POS 5 +#define BTMR_CR_RLD_POS 6 +#define BTMR_CR_HALT_POS 7 +#define BTMR_CR_PS_POS 16 +#define BTMR_CR_PS_MSK GENMASK(31, 16) +#define BTMR_CR_PS_SET(n) FIELD_PREP(BTMR_CR_PS_MSK, (n)) +#define BMTR_CR_PS_GET(n) FIELD_GET(BTMR_CR_PS_MSK, (n)) + +#endif /* * The spinlock protects all access to the RTMR registers, as well as @@ -104,44 +135,12 @@ static struct k_spinlock lock; static uint32_t total_cycles; static uint32_t cached_icr = CYCLES_PER_TICK; -/* - * NOTE: using inline for speed instead of call to external SoC function. - * MEC GIRQ numbers are documented as 8 to 26, check and convert to zero - * based index. - */ -static inline void girq_src_clr(int girq, int bitpos) -{ - if ((girq < 8) || (girq > 26)) { - return; - } - - ECIA_XEC_REGS->GIRQ[girq - 8].SRC = BIT(bitpos); -} - -static inline void girq_src_en(int girq, int bitpos) +static inline void timer_restart(uint32_t countdown) { - if ((girq < 8) || (girq > 26)) { - return; - } - - ECIA_XEC_REGS->GIRQ[girq - 8].EN_SET = BIT(bitpos); -} - -static inline void girq_src_dis(int girq, int bitpos) -{ - if ((girq < 8) || (girq > 26)) { - return; - } - - ECIA_XEC_REGS->GIRQ[girq - 8].EN_CLR = BIT(bitpos); -} - -static void timer_restart(uint32_t countdown) -{ - TIMER_REGS->CTRL = 0U; - TIMER_REGS->CTRL = MCHP_RTMR_CTRL_BLK_EN; - TIMER_REGS->PRLD = countdown; - TIMER_REGS->CTRL = TIMER_START_VAL; + sys_write32(0, TIMER_BASE + TIMER_CR_OFS); + sys_write32(BIT(TIMER_CR_ACTV_POS), TIMER_BASE + TIMER_CR_OFS); + sys_write32(countdown, TIMER_BASE + TIMER_PRLD_OFS); + sys_write32(TIMER_START_VAL, TIMER_BASE + TIMER_CR_OFS); } /* @@ -158,9 +157,9 @@ static void timer_restart(uint32_t countdown) */ static inline uint32_t timer_count(void) { - uint32_t ccr = TIMER_REGS->CNT; + uint32_t ccr = sys_read32(TIMER_BASE + TIMER_CNT_OFS); - if ((ccr == 0) && (TIMER_REGS->CTRL & MCHP_RTMR_CTRL_START)) { + if ((ccr == 0) && sys_test_bit(TIMER_BASE + TIMER_CR_OFS, TIMER_CR_START_POS)) { ccr = cached_icr; } @@ -169,7 +168,7 @@ static inline uint32_t timer_count(void) #ifdef CONFIG_TICKLESS_KERNEL -static uint32_t last_announcement; /* last time we called sys_clock_announce() */ +static uint32_t last_announcement; /* last time we called sys_clock_announce() */ /* * Request a timeout n Zephyr ticks in the future from now. @@ -188,16 +187,16 @@ void sys_clock_set_timeout(int32_t n, bool idle) ARG_UNUSED(idle); uint32_t ccr, temp; - int full_ticks; /* number of complete ticks we'll wait */ - uint32_t full_cycles; /* full_ticks represented as cycles */ - uint32_t partial_cycles; /* number of cycles to first tick boundary */ + int full_ticks; /* number of complete ticks we'll wait */ + uint32_t full_cycles; /* full_ticks represented as cycles */ + uint32_t partial_cycles; /* number of cycles to first tick boundary */ if (idle && (n == K_TICKS_FOREVER)) { /* * We are not in a locked section. Are writes to two * global objects safe from pre-emption? */ - TIMER_REGS->CTRL = 0U; /* stop timer */ + sys_write32(0, TIMER_BASE + TIMER_CR_OFS); /* stop timer */ cached_icr = TIMER_STOPPED; return; } @@ -217,8 +216,8 @@ void sys_clock_set_timeout(int32_t n, bool idle) ccr = timer_count(); /* turn off to clear any pending interrupt status */ - TIMER_REGS->CTRL = 0u; - girq_src_clr(TIMER_GIRQ, TIMER_GIRQ_POS); + sys_write32(0, TIMER_BASE + TIMER_CR_OFS); + sys_write32(BIT(TIMER_GIRQ_BITPOS), TIMER_GIRQ_BASE + GIRQ_SRC_OFS); NVIC_ClearPendingIRQ(TIMER_NVIC_NO); temp = total_cycles; @@ -278,7 +277,7 @@ static void xec_rtos_timer_isr(const void *arg) k_spinlock_key_t key = k_spin_lock(&lock); - girq_src_clr(TIMER_GIRQ, TIMER_GIRQ_POS); + sys_write32(BIT(TIMER_GIRQ_BITPOS), TIMER_GIRQ_BASE + GIRQ_SRC_OFS); /* Restart the timer as early as possible to minimize drift... */ timer_restart(MAX_TICKS * CYCLES_PER_TICK); @@ -310,7 +309,7 @@ static void xec_rtos_timer_isr(const void *arg) k_spinlock_key_t key = k_spin_lock(&lock); - girq_src_clr(TIMER_GIRQ, TIMER_GIRQ_POS); + sys_write32(BIT(TIMER_GIRQ_BITPOS), TIMER_GIRQ_BASE + GIRQ_SRC_OFS); /* Restart the timer as early as possible to minimize drift... */ timer_restart(cached_icr); @@ -365,7 +364,7 @@ void sys_clock_idle_exit(void) void sys_clock_disable(void) { - TIMER_REGS->CTRL = 0U; + sys_write32(0, TIMER_BASE + TIMER_CR_OFS); } #ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT @@ -386,10 +385,10 @@ void arch_busy_wait(uint32_t usec_to_wait) return; } - uint32_t start = BTMR32_0_REGS->CNT; + uint32_t start = sys_read32(BTMR_BASE + BTMR_CNT_OFS); for (;;) { - uint32_t curr = BTMR32_0_REGS->CNT; + uint32_t curr = sys_read32(BTMR_BASE + BTMR_CNT_OFS); if ((curr - start) >= usec_to_wait) { break; @@ -400,43 +399,33 @@ void arch_busy_wait(uint32_t usec_to_wait) static int sys_clock_driver_init(void) { - #ifdef CONFIG_TICKLESS_KERNEL cached_icr = MAX_TICKS; #endif - TIMER_REGS->CTRL = 0u; - girq_src_clr(TIMER_GIRQ, TIMER_GIRQ_POS); - girq_src_dis(TIMER_GIRQ, TIMER_GIRQ_POS); + sys_write32(0, TIMER_BASE + TIMER_CR_OFS); + sys_write32(BIT(TIMER_GIRQ_BITPOS), TIMER_GIRQ_BASE + GIRQ_ENCLR_OFS); + sys_write32(BIT(TIMER_GIRQ_BITPOS), TIMER_GIRQ_BASE + GIRQ_SRC_OFS); NVIC_ClearPendingIRQ(TIMER_NVIC_NO); IRQ_CONNECT(TIMER_NVIC_NO, TIMER_NVIC_PRIO, xec_rtos_timer_isr, 0, 0); irq_enable(TIMER_NVIC_NO); - girq_src_en(TIMER_GIRQ, TIMER_GIRQ_POS); + sys_write32(BIT(TIMER_GIRQ_BITPOS), TIMER_GIRQ_BASE + GIRQ_ENSET_OFS); #ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT - uint32_t btmr_ctrl = (MCHP_BTMR_CTRL_ENABLE - | MCHP_BTMR_CTRL_AUTO_RESTART - | MCHP_BTMR_CTRL_COUNT_UP - | (47UL << MCHP_BTMR_CTRL_PRESCALE_POS)); + uint32_t btmr_ctrl = (BIT(BTMR_CR_ACTV_POS) | BIT(BTMR_CR_ARS_POS) | + BIT(BTMR_CR_CNT_UP_POS) | BTMR_CR_PS_SET(47u)); -#if CONFIG_SOC_SERIES_MEC15XX - mchp_pcr_periph_slp_ctrl(PCR_B32TMR0, 0); -#else - PCR_XEC_REGS->SLP_EN[BTMR32_0_PCR_REG_IDX] &= ~BIT(BTMR32_0_PCR_BITPOS); -#endif - BTMR32_0_REGS->CTRL = MCHP_BTMR_CTRL_SOFT_RESET; - BTMR32_0_REGS->CTRL = btmr_ctrl; - BTMR32_0_REGS->PRLD = UINT32_MAX; - btmr_ctrl |= MCHP_BTMR_CTRL_START; + sys_write32(BIT(BTMR_CR_SOFT_RST_POS), BTMR_BASE + BTMR_CR_OFS); + sys_write32(btmr_ctrl, BTMR_BASE + BTMR_CR_OFS); + sys_write32(UINT32_MAX, BTMR_BASE + BTMR_PRLD_OFS); + sys_set_bit(BTMR_BASE + BTMR_CR_OFS, BTMR_CR_START_POS); timer_restart(cached_icr); /* wait for RTOS timer to load count register from preload */ - while (TIMER_REGS->CNT == 0) { + while (sys_read32(BTMR_BASE + BTMR_CNT_OFS) == 0) { ; } - - BTMR32_0_REGS->CTRL = btmr_ctrl; #else timer_restart(cached_icr); #endif @@ -444,5 +433,4 @@ static int sys_clock_driver_init(void) return 0; } -SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, - CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/dts/arm/microchip/mec/mec1501hsz.dtsi b/dts/arm/microchip/mec/mec1501hsz.dtsi index 794b07ac4da6..f6a3afd23956 100644 --- a/dts/arm/microchip/mec/mec1501hsz.dtsi +++ b/dts/arm/microchip/mec/mec1501hsz.dtsi @@ -163,6 +163,7 @@ interrupts = <111 0>; clock-frequency = <32768>; girqs = <23 10>; + busy-wait-timer = <&timer5>; }; bbram: bb-ram@4000a800 { compatible = "microchip,xec-bbram"; diff --git a/dts/arm/microchip/mec/mec172x_common.dtsi b/dts/arm/microchip/mec/mec172x_common.dtsi index 45f673809ecf..88b76748fa3d 100644 --- a/dts/arm/microchip/mec/mec172x_common.dtsi +++ b/dts/arm/microchip/mec/mec172x_common.dtsi @@ -292,6 +292,7 @@ rtimer: timer@40007400 { interrupts = <111 0>; clock-frequency = <32768>; girqs = <23 10>; + busy-wait-timer = <&timer5>; }; timer0: timer@40000c00 { compatible = "microchip,xec-timer"; diff --git a/dts/arm/microchip/mec/mec5.dtsi b/dts/arm/microchip/mec/mec5.dtsi index e21e470a6765..8ee4948a9506 100644 --- a/dts/arm/microchip/mec/mec5.dtsi +++ b/dts/arm/microchip/mec/mec5.dtsi @@ -210,13 +210,16 @@ status = "disabled"; }; rtimer: timer@40007400 { + compatible = "microchip,xec-rtos-timer"; reg = <0x40007400 0x10>; interrupts = <111 0>; + girqs = <23 10>; clock-frequency = <32768>; - max-value = <0xffffffff>; + busy-wait-timer = <&timer5>; status = "disabled"; }; timer0: timer@40000c00 { + compatible = "microchip,xec-basic-timer"; reg = <0x40000c00 0x20>; interrupts = <136 0>; clock-frequency = <48000000>; @@ -225,6 +228,7 @@ status = "disabled"; }; timer1: timer@40000c20 { + compatible = "microchip,xec-basic-timer"; reg = <0x40000c20 0x20>; interrupts = <137 0>; clock-frequency = <48000000>; @@ -233,6 +237,7 @@ status = "disabled"; }; timer2: timer@40000c40 { + compatible = "microchip,xec-basic-timer"; reg = <0x40000c40 0x20>; interrupts = <138 0>; clock-frequency = <48000000>; @@ -241,6 +246,7 @@ status = "disabled"; }; timer3: timer@40000c60 { + compatible = "microchip,xec-basic-timer"; reg = <0x40000c60 0x20>; interrupts = <139 0>; clock-frequency = <48000000>; @@ -249,6 +255,7 @@ status = "disabled"; }; timer4: timer@40000c80 { + compatible = "microchip,xec-basic-timer"; reg = <0x40000c80 0x20>; interrupts = <140 0>; clock-frequency = <48000000>; @@ -257,6 +264,7 @@ status = "disabled"; }; timer5: timer@40000ca0 { + compatible = "microchip,xec-basic-timer"; reg = <0x40000ca0 0x20>; interrupts = <141 0>; clock-frequency = <48000000>; diff --git a/dts/bindings/interrupt-controller/microchip,dmec-ecia-girq.yaml b/dts/bindings/interrupt-controller/microchip,dmec-ecia-girq.yaml new file mode 100644 index 000000000000..6b5a028ca18b --- /dev/null +++ b/dts/bindings/interrupt-controller/microchip,dmec-ecia-girq.yaml @@ -0,0 +1,23 @@ +description: Microchip DEC/MEC series External Interrupt Aggregator GIRQ + +compatible: "microchip,dmec-ecia-girq" + +include: base.yaml + +properties: + girqs: + type: array + required: true + description: | + Many DEC/MEC periperals interrupt signals are direct capable. The signals are + connected to bits in a GIRQ. Each GIRQ is composed of 5 32-bit registers: + status(latched or r/w1-c), set-enable, clr-enable, and result (read-only). + The read-only result register bits are the bitwise AND of status and enable. + Direct mode routes the individual result register bits to NVIC inputs. If + direct mode is disable by setting direct mode bit to 0 in the EC subsystem + interrupt control register then the result register outputs are OR'd together + and the OR'd result is connected to an NVIC input based on GIRQ number. + To enable an interrupt a driver must know: + a. NVIC input number and priority from the interrupts property + b. GIRQ number and bit position from the girqs property + The number of entries in interrupts and girqs should be the same in a DT node. diff --git a/dts/bindings/timer/microchip,mec5-ktimer.yaml b/dts/bindings/timer/microchip,mec5-ktimer.yaml deleted file mode 100644 index d498650a09e7..000000000000 --- a/dts/bindings/timer/microchip,mec5-ktimer.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2019 Microchip Technology Inc. -# SPDX-License-Identifier: Apache-2.0 - -description: | - Microchip MEC5 kernel timer implemented by combining - the 32kHz 32-bit RTOS timer with 32-bit basic timer 5. - -compatible: "microchip,mec5-ktimer" - -include: base.yaml - -properties: - reg: - required: true - - interrupts: - required: true - - clock-frequency: - type: int - required: true - const: 32768 - description: RTOS timer runs at fixed 32 KHz. - - max-value: - type: int - required: true - const: 0xffffffff - description: RTOS timer counter maximum value. diff --git a/dts/bindings/timer/microchip,xec-basic-timer.yaml b/dts/bindings/timer/microchip,xec-basic-timer.yaml new file mode 100644 index 000000000000..3ba650f2d5c8 --- /dev/null +++ b/dts/bindings/timer/microchip,xec-basic-timer.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2025 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Microchip XEC basic timer properties + +compatible: "microchip,xec-basic-timer" + +include: ["base.yaml", "microchip,dmec-ecia-girq.yaml"] + +properties: + reg: + required: true + + interrupts: + required: true + + clock-frequency: + type: int + required: true + const: 48000000 + description: Basic timer input clock is 48 MHz. + + max-value: + type: int + required: true + description: | + Counter maximum value. The SoC contains multiple instances + of the basic timer. Some are 16-bit, others 32-bit. + + prescaler: + type: int + required: true + description: | + Basic timer implements a 16-bit clock prescale value. + Count frequency is clock-frequency divided by (prescaler + 1). diff --git a/dts/bindings/timer/microchip,xec-rtos-timer.yaml b/dts/bindings/timer/microchip,xec-rtos-timer.yaml index 509634082ddd..f3281377ca55 100644 --- a/dts/bindings/timer/microchip,xec-rtos-timer.yaml +++ b/dts/bindings/timer/microchip,xec-rtos-timer.yaml @@ -5,7 +5,7 @@ description: Microchip XEC RTOS timer compatible: "microchip,xec-rtos-timer" -include: base.yaml +include: ["base.yaml", "microchip,dmec-ecia-girq.yaml"] properties: reg: @@ -14,10 +14,11 @@ properties: interrupts: required: true - girqs: - type: array - required: true - description: Array of GIRQ numbers [8:26] and bit positions [0:31]. + busy-wait-timer: + type: phandle + description: | + If custom busy wait Kconfig is enabled then this points to the 32-bit + basic timer node used to implement the 1 MHz busy wait timer. clock-frequency: type: int diff --git a/soc/microchip/mec/mec174x/Kconfig.defconfig.series b/soc/microchip/mec/mec174x/Kconfig.defconfig.series index 2b750776fe97..c355b91477ef 100644 --- a/soc/microchip/mec/mec174x/Kconfig.defconfig.series +++ b/soc/microchip/mec/mec174x/Kconfig.defconfig.series @@ -12,15 +12,18 @@ config NUM_IRQS default 194 config CORTEX_M_SYSTICK - depends on !MCHP_MEC5_KTIMER + depends on !MCHP_XEC_RTOS_TIMER config SYS_CLOCK_HW_CYCLES_PER_SEC default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if CORTEX_M_SYSTICK - default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) if MCHP_MEC5_KTIMER + default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) if MCHP_XEC_RTOS_TIMER -if MCHP_MEC5_KTIMER +if MCHP_XEC_RTOS_TIMER config SYS_CLOCK_TICKS_PER_SEC default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) -endif # MCHP_MEC5_KTIMER +endif # MCHP_XEC_RTOS_TIMER + +config ARCH_HAS_CUSTOM_BUSY_WAIT + default y endif # SOC_SERIES_MEC174X diff --git a/soc/microchip/mec/mec175x/Kconfig.defconfig.series b/soc/microchip/mec/mec175x/Kconfig.defconfig.series index e32cacf68cd7..dbc85c6789ef 100644 --- a/soc/microchip/mec/mec175x/Kconfig.defconfig.series +++ b/soc/microchip/mec/mec175x/Kconfig.defconfig.series @@ -12,15 +12,18 @@ config NUM_IRQS default 198 config CORTEX_M_SYSTICK - depends on !MCHP_MEC5_KTIMER + depends on !MCHP_XEC_RTOS_TIMER config SYS_CLOCK_HW_CYCLES_PER_SEC default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if CORTEX_M_SYSTICK - default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) if MCHP_MEC5_KTIMER + default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) if MCHP_XEC_RTOS_TIMER -if MCHP_MEC5_KTIMER +if MCHP_XEC_RTOS_TIMER config SYS_CLOCK_TICKS_PER_SEC default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) -endif # MCHP_MEC5_KTIMER +endif # MCHP_XEC_RTOS_TIMER + +config ARCH_HAS_CUSTOM_BUSY_WAIT + default y endif # SOC_SERIES_MEC175X diff --git a/soc/microchip/mec/mech172x/Kconfig.defconfig.series b/soc/microchip/mec/mech172x/Kconfig.defconfig.series index ddb1a4a2850b..a466fb15e1a0 100644 --- a/soc/microchip/mec/mech172x/Kconfig.defconfig.series +++ b/soc/microchip/mec/mech172x/Kconfig.defconfig.series @@ -12,15 +12,18 @@ config NUM_IRQS default 181 config CORTEX_M_SYSTICK - depends on !MCHP_MEC5_KTIMER + depends on !MCHP_XEC_RTOS_TIMER config SYS_CLOCK_HW_CYCLES_PER_SEC default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if CORTEX_M_SYSTICK - default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) if MCHP_MEC5_KTIMER + default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) if MCHP_XEC_RTOS_TIMER -if MCHP_MEC5_KTIMER +if MCHP_XEC_RTOS_TIMER config SYS_CLOCK_TICKS_PER_SEC default $(dt_node_int_prop_int,/soc/timer@40007400,clock-frequency) -endif # MCHP_MEC5_KTIMER +endif # MCHP_XEC_RTOS_TIMER + +config ARCH_HAS_CUSTOM_BUSY_WAIT + default y endif # SOC_SERIES_MECH172X