diff --git a/arch/arm/include/armv7-r/cp15.h b/arch/arm/include/armv7-r/cp15.h index 4f4f49e6c1833..6d0ec2fb5f978 100644 --- a/arch/arm/include/armv7-r/cp15.h +++ b/arch/arm/include/armv7-r/cp15.h @@ -159,9 +159,10 @@ #define CP15_CNTV_TVAL(r) _CP15(0, r, c14, c3, 0) /* Virtual TimerValue register */ #define CP15_CNTV_CTL(r) _CP15(0, r, c14, c3, 1) /* Virtual Timer Control register */ -#define CP15_CNTPCT(lo,hi) _CP15_64(0, lo, hi, c14) /* Physical Count register */ - +#define CP15_CNTPCT(lo,hi) _CP15_64(0, lo, hi, c14) /* Physical Count register */ +#define CP15_CNTVCT(lo,hi) _CP15_64(1, lo, hi, c14) /* Virtual Count register */ #define CP15_CNTP_CVAL(lo,hi) _CP15_64(2, lo, hi, c14) /* Physical Timer CompareValue register */ +#define CP15_CNTV_CVAL(lo,hi) _CP15_64(3, lo, hi, c14) /* Virtual Timer CompareValue register */ #define CP15_DCIALLU(r) _CP15(0, r, c15, c5, 0) /* Invalidate data cache */ diff --git a/arch/arm/include/armv8-r/cp15.h b/arch/arm/include/armv8-r/cp15.h index 8b352da27441c..0db902539d676 100644 --- a/arch/arm/include/armv8-r/cp15.h +++ b/arch/arm/include/armv8-r/cp15.h @@ -162,12 +162,16 @@ #define CP15_TPIDRURO(r) _CP15(0, r, c13, c0, 3) #define CP15_TPIDRPRW(r) _CP15(0, r, c13, c0, 4) -#define CP15_CNTFRQ(r) _CP15(0, r, c14, c0, 0) /* CNTFRQ */ -#define CP15_CNTVCT(lo,hi) _CP15_64(1, lo, hi, c14) /* CNTVCT */ -#define CP15_CNTV_CTL(r) _CP15(0, r, c14, c3, 1) /* CNTV_CTL */ -#define CP15_CNTV_CVAL(lo,hi) _CP15_64(3, lo, hi, c14) /* CNTV_CVAL */ - -#define CP15_CNTPCT(lo,hi) _CP15_64(0, lo, hi, c14) /* Physical Count register */ +#define CP15_CNTFRQ(r) _CP15(0, r, c14, c0, 0) /* Timer frequency register */ +#define CP15_CNTV_CTL(r) _CP15(0, r, c14, c3, 1) /* Virtual Timer Control register */ +#define CP15_CNTV_TVAL(r) _CP15(0, r, c14, c3, 0) /* Virtual TimerValue register */ +#define CP15_CNTP_CTL(r) _CP15(0, r, c14, c2, 1) /* PL1 Physical Timer Control register */ +#define CP15_CNTP_TVAL(r) _CP15(0, r, c14, c2, 0) /* PL1 Physical TimerValue register */ + +#define CP15_CNTVCT(lo,hi) _CP15_64(1, lo, hi, c14) /* Virtual Count register */ +#define CP15_CNTV_CVAL(lo,hi) _CP15_64(3, lo, hi, c14) /* Virtual Timer CompareValue register */ +#define CP15_CNTPCT(lo,hi) _CP15_64(0, lo, hi, c14) /* PL1 Physical Count register */ +#define CP15_CNTP_CVAL(lo,hi) _CP15_64(2, lo, hi, c14) /* PL1 Physical Timer CompareValue register */ #define CP15_DCIALLU(r) _CP15(0, r, c15, c5, 0) /* Invalidate data cache */ diff --git a/arch/arm/src/armv7-a/arm_timer.c b/arch/arm/src/armv7-a/arm_timer.c index 65faafa8bdec6..81da492a9b6c6 100644 --- a/arch/arm/src/armv7-a/arm_timer.c +++ b/arch/arm/src/armv7-a/arm_timer.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -39,9 +40,15 @@ * Pre-processor Definitions ****************************************************************************/ -#define ARM_TIMER_CTRL_ENABLE (1 << 0) -#define ARM_TIMER_CTRL_INT_MASK (1 << 1) -#define ARM_TIMER_CTRL_INT_STAT (1 << 2) +#define CNT_CTL_ENABLE_BIT 0 +#define CNT_CTL_IMASK_BIT 1 +#define CNT_CTL_ISTATUS_BIT 2 + +#ifdef CONFIG_ARCH_TRUSTZONE_SECURE +# define GIC_IRQ_TIMER GIC_IRQ_STM +#else +# define GIC_IRQ_TIMER GIC_IRQ_PTM +#endif /**************************************************************************** * Private Types @@ -58,7 +65,6 @@ struct arm_timer_lowerhalf_s uint32_t freq; /* Timer working clock frequency(Hz) */ oneshot_callback_t callback; /* Current user interrupt callback */ void *arg; /* Argument passed to upper half callback */ - bool init[CONFIG_SMP_NCPUS]; /* True: timer is init */ /* which cpu timer is running, -1 indicate timer stoppd */ @@ -91,6 +97,8 @@ static const struct oneshot_operations_s g_arm_timer_ops = .current = arm_timer_current, }; +static struct arm_timer_lowerhalf_s g_arm_timer_lowerhalf; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -98,49 +106,39 @@ static const struct oneshot_operations_s g_arm_timer_ops = static inline void arm_timer_set_freq(uint32_t freq) { CP15_SET(CNTFRQ, freq); - UP_ISB(); } -static inline uint64_t arm_timer_get_count(void) +static inline uint64_t arm_timer_phy_count(void) { - UP_ISB(); return CP15_GET64(CNTPCT); } -static inline uint32_t arm_timer_get_ctrl(void) +static inline void arm_timer_phy_set_relative(uint32_t tval) { - UP_ISB(); - return CP15_GET(CNTP_CTL); + CP15_SET(CNTP_TVAL, tval); } -static inline void arm_timer_set_ctrl(uint32_t ctrl) +static inline void arm_timer_phy_set_absolute(uint64_t cval) { - CP15_SET(CNTP_CTL, ctrl); - UP_ISB(); + CP15_SET64(CNTP_CVAL, cval); } -static inline uint32_t arm_timer_get_tval(void) +static inline void arm_timer_phy_enable(bool enable) { - UP_ISB(); - return CP15_GET(CNTP_TVAL); + CP15_MODIFY((uint32_t)enable << CNT_CTL_ENABLE_BIT, + BIT(CNT_CTL_ENABLE_BIT), CNTP_CTL); } -static inline void arm_timer_set_tval(uint32_t tval) +static inline void arm_timer_phy_set_irq_mask(bool mask) { - CP15_SET(CNTP_TVAL, tval); - UP_ISB(); + CP15_MODIFY((uint32_t)mask << CNT_CTL_IMASK_BIT, + BIT(CNT_CTL_IMASK_BIT), CNTP_CTL); } -static inline uint64_t arm_timer_get_cval(void) +static inline void arm_timer_virt_set_irq_mask(bool mask) { - UP_ISB(); - return CP15_GET64(CNTP_CVAL); -} - -static inline void arm_timer_set_cval(uint64_t cval) -{ - CP15_SET64(CNTP_CVAL, cval); - UP_ISB(); + CP15_MODIFY((uint32_t)mask << CNT_CTL_IMASK_BIT, + BIT(CNT_CTL_IMASK_BIT), CNTV_CTL); } static inline uint64_t nsec_from_count(uint64_t count, uint32_t freq) @@ -179,43 +177,20 @@ static int arm_timer_start(struct oneshot_lowerhalf_s *lower_, (struct arm_timer_lowerhalf_s *)lower_; irqstate_t flags; uint64_t count; - uint32_t ctrl; flags = up_irq_save(); lower->callback = callback; lower->arg = arg; - if (!lower->init[this_cpu()]) - { - if (lower->freq) - { - arm_timer_set_freq(lower->freq); - } - - /* Enable timer */ - - ctrl = arm_timer_get_ctrl(); - ctrl |= ARM_TIMER_CTRL_ENABLE | ARM_TIMER_CTRL_INT_MASK; - arm_timer_set_ctrl(ctrl); -#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) - up_enable_irq(GIC_IRQ_STM); -#else - up_enable_irq(GIC_IRQ_PTM); -#endif - - lower->init[this_cpu()] = true; - } - lower->running = this_cpu(); - count = sec_to_count(ts->tv_sec, arm_timer_get_freq()) + - nsec_to_count(ts->tv_nsec, arm_timer_get_freq()); - arm_timer_set_cval(arm_timer_get_count() + count); + count = sec_to_count(ts->tv_sec, lower->freq) + + nsec_to_count(ts->tv_nsec, lower->freq); - ctrl = arm_timer_get_ctrl(); - ctrl &= ~ARM_TIMER_CTRL_INT_MASK; - arm_timer_set_ctrl(ctrl); + arm_timer_phy_set_relative(count > UINT32_MAX ? UINT32_MAX : count); + + arm_timer_phy_set_irq_mask(false); up_irq_restore(flags); @@ -228,7 +203,6 @@ static int arm_timer_cancel(struct oneshot_lowerhalf_s *lower_, struct arm_timer_lowerhalf_s *lower = (struct arm_timer_lowerhalf_s *)lower_; irqstate_t flags; - uint32_t ctrl; flags = up_irq_save(); @@ -236,9 +210,7 @@ static int arm_timer_cancel(struct oneshot_lowerhalf_s *lower_, lower->arg = NULL; lower->running = -1; - ctrl = arm_timer_get_ctrl(); - ctrl |= ARM_TIMER_CTRL_INT_MASK; - arm_timer_set_ctrl(ctrl); + arm_timer_phy_set_irq_mask(true); up_irq_restore(flags); @@ -248,8 +220,10 @@ static int arm_timer_cancel(struct oneshot_lowerhalf_s *lower_, static int arm_timer_current(struct oneshot_lowerhalf_s *lower_, struct timespec *ts) { - uint64_t nsec = nsec_from_count(arm_timer_get_count(), - arm_timer_get_freq()); + struct arm_timer_lowerhalf_s *lower = + (struct arm_timer_lowerhalf_s *)lower_; + uint64_t nsec = nsec_from_count(arm_timer_phy_count(), + lower->freq); ts->tv_sec = nsec / NSEC_PER_SEC; ts->tv_nsec = nsec % NSEC_PER_SEC; @@ -265,7 +239,7 @@ static int arm_timer_interrupt(int irq, void *context, void *arg) DEBUGASSERT(lower != NULL); - arm_timer_set_ctrl(arm_timer_get_ctrl() | ARM_TIMER_CTRL_INT_MASK); + arm_timer_phy_set_irq_mask(true); if (lower->callback != NULL && lower->running == this_cpu()) { @@ -282,35 +256,41 @@ static int arm_timer_interrupt(int irq, void *context, void *arg) return 0; } +static void arm_timer_initialize_per_cpu(unsigned int freq) +{ + /* Enable timer */ + + if (freq) + { + arm_timer_set_freq(freq); + } + + arm_timer_phy_set_irq_mask(true); + arm_timer_phy_enable(true); + + up_enable_irq(GIC_IRQ_TIMER); +} + /**************************************************************************** * Public Functions ****************************************************************************/ -uint32_t arm_timer_get_freq(void) -{ - UP_ISB(); - return CP15_GET(CNTFRQ); -} - struct oneshot_lowerhalf_s *arm_timer_initialize(unsigned int freq) { - struct arm_timer_lowerhalf_s *lower; + struct arm_timer_lowerhalf_s *lower = &g_arm_timer_lowerhalf; - lower = kmm_zalloc(sizeof(*lower)); - if (lower == NULL) - { - return NULL; - } + arm_timer_initialize_per_cpu(freq); + lower->freq = arm_timer_get_freq(); lower->lh.ops = &g_arm_timer_ops; - lower->freq = freq; lower->running = -1; -#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) - irq_attach(GIC_IRQ_STM, arm_timer_interrupt, lower); -#else - irq_attach(GIC_IRQ_PTM, arm_timer_interrupt, lower); -#endif + irq_attach(GIC_IRQ_TIMER, arm_timer_interrupt, lower); return (struct oneshot_lowerhalf_s *)lower; } + +void arm_timer_secondary_init(unsigned int freq) +{ + arm_timer_initialize_per_cpu(freq); +} diff --git a/arch/arm/src/armv7-a/arm_timer.h b/arch/arm/src/armv7-a/arm_timer.h index 7d70eeede9445..cd6d7217d6236 100644 --- a/arch/arm/src/armv7-a/arm_timer.h +++ b/arch/arm/src/armv7-a/arm_timer.h @@ -30,6 +30,14 @@ #include #include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define arm_timer_get_freq() CP15_GET(CNTFRQ) + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -61,10 +69,8 @@ extern "C" #ifdef CONFIG_ARMV7A_HAVE_PTM struct oneshot_lowerhalf_s *arm_timer_initialize(unsigned int freq); -uint32_t arm_timer_get_freq(void); #else # define arm_timer_initialize(freq) NULL -# define arm_timer_get_freq() 0 #endif #undef EXTERN diff --git a/arch/arm/src/armv7-r/arm_timer.c b/arch/arm/src/armv7-r/arm_timer.c index 2e69426cfafd9..c97f3b7ec7bad 100644 --- a/arch/arm/src/armv7-r/arm_timer.c +++ b/arch/arm/src/armv7-r/arm_timer.c @@ -26,8 +26,10 @@ #include #include +#include #include #include + #include #include "arm_timer.h" @@ -37,9 +39,15 @@ * Pre-processor Definitions ****************************************************************************/ -#define ARM_TIMER_CTRL_ENABLE (1 << 0) -#define ARM_TIMER_CTRL_INT_MASK (1 << 1) -#define ARM_TIMER_CTRL_INT_STAT (1 << 2) +#define CNT_CTL_ENABLE_BIT 0 +#define CNT_CTL_IMASK_BIT 1 +#define CNT_CTL_ISTATUS_BIT 2 + +#ifdef CONFIG_ARCH_TRUSTZONE_SECURE +# define GIC_IRQ_TIMER GIC_IRQ_STM +#else +# define GIC_IRQ_TIMER GIC_IRQ_PTM +#endif /**************************************************************************** * Private Types @@ -56,7 +64,6 @@ struct arm_timer_lowerhalf_s uint32_t freq; /* Timer working clock frequency(Hz) */ oneshot_callback_t callback; /* Current user interrupt callback */ void *arg; /* Argument passed to upper half callback */ - bool init[CONFIG_SMP_NCPUS]; /* True: timer is init */ /* which cpu timer is running, -1 indicate timer stoppd */ @@ -89,6 +96,8 @@ static const struct oneshot_operations_s g_arm_timer_ops = .current = arm_timer_current, }; +static struct arm_timer_lowerhalf_s g_arm_timer_lowerhalf; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -96,49 +105,33 @@ static const struct oneshot_operations_s g_arm_timer_ops = static inline void arm_timer_set_freq(uint32_t freq) { CP15_SET(CNTFRQ, freq); - UP_ISB(); } -static inline uint64_t arm_timer_get_count(void) +static inline uint64_t arm_timer_phy_count(void) { - UP_ISB(); return CP15_GET64(CNTPCT); } -static inline uint32_t arm_timer_get_ctrl(void) -{ - UP_ISB(); - return CP15_GET(CNTP_CTL); -} - -static inline void arm_timer_set_ctrl(uint32_t ctrl) -{ - CP15_SET(CNTP_CTL, ctrl); - UP_ISB(); -} - -static inline uint32_t arm_timer_get_tval(void) +static inline void arm_timer_phy_set_relative(uint32_t tval) { - UP_ISB(); - return CP15_GET(CNTP_TVAL); + CP15_SET(CNTP_TVAL, tval); } -static inline void arm_timer_set_tval(uint32_t tval) +static inline void arm_timer_phy_set_absolute(uint64_t cval) { - CP15_SET(CNTP_TVAL, tval); - UP_ISB(); + CP15_SET64(CNTP_CVAL, cval); } -static inline uint64_t arm_timer_get_cval(void) +static inline void arm_timer_phy_enable(bool enable) { - UP_ISB(); - return CP15_GET64(CNTP_CVAL); + CP15_MODIFY((uint32_t)enable << CNT_CTL_ENABLE_BIT, + BIT(CNT_CTL_ENABLE_BIT), CNTP_CTL); } -static inline void arm_timer_set_cval(uint64_t cval) +static inline void arm_timer_phy_set_irq_mask(bool mask) { - CP15_SET64(CNTP_CVAL, cval); - UP_ISB(); + CP15_MODIFY((uint32_t)mask << CNT_CTL_IMASK_BIT, + BIT(CNT_CTL_IMASK_BIT), CNTP_CTL); } static inline uint64_t nsec_from_count(uint64_t count, uint32_t freq) @@ -177,43 +170,20 @@ static int arm_timer_start(struct oneshot_lowerhalf_s *lower_, (struct arm_timer_lowerhalf_s *)lower_; irqstate_t flags; uint64_t count; - uint32_t ctrl; flags = up_irq_save(); lower->callback = callback; lower->arg = arg; - if (!lower->init[this_cpu()]) - { - if (lower->freq) - { - arm_timer_set_freq(lower->freq); - } - - /* Enable timer */ - - ctrl = arm_timer_get_ctrl(); - ctrl |= ARM_TIMER_CTRL_ENABLE | ARM_TIMER_CTRL_INT_MASK; - arm_timer_set_ctrl(ctrl); -#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) - up_enable_irq(GIC_IRQ_STM); -#else - up_enable_irq(GIC_IRQ_PTM); -#endif - - lower->init[this_cpu()] = true; - } - lower->running = this_cpu(); count = sec_to_count(ts->tv_sec, arm_timer_get_freq()) + nsec_to_count(ts->tv_nsec, arm_timer_get_freq()); - arm_timer_set_cval(arm_timer_get_count() + count); - ctrl = arm_timer_get_ctrl(); - ctrl &= ~ARM_TIMER_CTRL_INT_MASK; - arm_timer_set_ctrl(ctrl); + arm_timer_phy_set_relative(count > UINT32_MAX ? UINT32_MAX : count); + + arm_timer_phy_set_irq_mask(false); up_irq_restore(flags); @@ -226,7 +196,6 @@ static int arm_timer_cancel(struct oneshot_lowerhalf_s *lower_, struct arm_timer_lowerhalf_s *lower = (struct arm_timer_lowerhalf_s *)lower_; irqstate_t flags; - uint32_t ctrl; flags = up_irq_save(); @@ -234,9 +203,7 @@ static int arm_timer_cancel(struct oneshot_lowerhalf_s *lower_, lower->arg = NULL; lower->running = -1; - ctrl = arm_timer_get_ctrl(); - ctrl |= ARM_TIMER_CTRL_INT_MASK; - arm_timer_set_ctrl(ctrl); + arm_timer_phy_set_irq_mask(true); up_irq_restore(flags); @@ -246,7 +213,7 @@ static int arm_timer_cancel(struct oneshot_lowerhalf_s *lower_, static int arm_timer_current(struct oneshot_lowerhalf_s *lower_, struct timespec *ts) { - uint64_t nsec = nsec_from_count(arm_timer_get_count(), + uint64_t nsec = nsec_from_count(arm_timer_phy_count(), arm_timer_get_freq()); ts->tv_sec = nsec / NSEC_PER_SEC; @@ -263,7 +230,7 @@ static int arm_timer_interrupt(int irq, void *context, void *arg) DEBUGASSERT(lower != NULL); - arm_timer_set_ctrl(arm_timer_get_ctrl() | ARM_TIMER_CTRL_INT_MASK); + arm_timer_phy_set_irq_mask(true); if (lower->callback != NULL && lower->running == this_cpu()) { @@ -280,35 +247,41 @@ static int arm_timer_interrupt(int irq, void *context, void *arg) return 0; } +static void arm_timer_initialize_per_cpu(unsigned int freq) +{ + /* Enable timer */ + + if (freq) + { + arm_timer_set_freq(freq); + } + + arm_timer_phy_set_irq_mask(true); + arm_timer_phy_enable(true); + + up_enable_irq(GIC_IRQ_TIMER); +} + /**************************************************************************** * Public Functions ****************************************************************************/ -uint32_t arm_timer_get_freq(void) -{ - UP_ISB(); - return CP15_GET(CNTFRQ); -} - struct oneshot_lowerhalf_s *arm_timer_initialize(unsigned int freq) { - struct arm_timer_lowerhalf_s *lower; + struct arm_timer_lowerhalf_s *lower = &g_arm_timer_lowerhalf; - lower = kmm_zalloc(sizeof(*lower)); - if (lower == NULL) - { - return NULL; - } + arm_timer_initialize_per_cpu(freq); + lower->freq = arm_timer_get_freq(); lower->lh.ops = &g_arm_timer_ops; - lower->freq = freq; lower->running = -1; -#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) - irq_attach(GIC_IRQ_STM, arm_timer_interrupt, lower); -#else - irq_attach(GIC_IRQ_PTM, arm_timer_interrupt, lower); -#endif + irq_attach(GIC_IRQ_TIMER, arm_timer_interrupt, lower); return (struct oneshot_lowerhalf_s *)lower; } + +void arm_timer_secondary_init(unsigned int freq) +{ + arm_timer_initialize_per_cpu(freq); +} diff --git a/arch/arm/src/armv7-r/arm_timer.h b/arch/arm/src/armv7-r/arm_timer.h index dd43f5718913d..be7801f6d03dc 100644 --- a/arch/arm/src/armv7-r/arm_timer.h +++ b/arch/arm/src/armv7-r/arm_timer.h @@ -30,6 +30,14 @@ #include #include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define arm_timer_get_freq() CP15_GET(CNTFRQ) + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -61,10 +69,8 @@ extern "C" #ifdef CONFIG_ARMV7R_HAVE_PTM struct oneshot_lowerhalf_s *arm_timer_initialize(unsigned int freq); -uint32_t arm_timer_get_freq(void); #else # define arm_timer_initialize(freq) NULL -# define arm_timer_get_freq() 0 #endif #undef EXTERN diff --git a/arch/arm/src/armv8-r/CMakeLists.txt b/arch/arm/src/armv8-r/CMakeLists.txt index 36c019dcefe21..23dcc0fd03320 100644 --- a/arch/arm/src/armv8-r/CMakeLists.txt +++ b/arch/arm/src/armv8-r/CMakeLists.txt @@ -33,7 +33,7 @@ list(APPEND SRCS arm_head.S arm_vectors.S arm_saveusercontext.S) list( APPEND SRCS - arm_arch_timer.c + arm_timer.c arm_cache.c arm_cpuinfo.c arm_dataabort.c diff --git a/arch/arm/src/armv8-r/Make.defs b/arch/arm/src/armv8-r/Make.defs index 0735cbf5547d2..8883d8e55f48c 100644 --- a/arch/arm/src/armv8-r/Make.defs +++ b/arch/arm/src/armv8-r/Make.defs @@ -31,7 +31,7 @@ HEAD_ASRC += arm_vectortab.S # Common assembly language files -CMN_CSRCS += arm_arch_timer.c arm_cache.c arm_cpuinfo.c arm_dataabort.c +CMN_CSRCS += arm_timer.c arm_cache.c arm_cpuinfo.c arm_dataabort.c CMN_CSRCS += arm_doirq.c arm_gicv3.c CMN_CSRCS += arm_initialstate.c arm_prefetchabort.c CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c diff --git a/arch/arm/src/armv8-r/arm_arch_timer.h b/arch/arm/src/armv8-r/arm_arch_timer.h deleted file mode 100644 index 21c8ce4aa58e5..0000000000000 --- a/arch/arm/src/armv8-r/arm_arch_timer.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** - * arch/arm/src/armv8-r/arm_arch_timer.h - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -#ifndef __ARCH_ARM_SRC_ARMV8_R_ARM_ARCH_TIMER_H -#define __ARCH_ARM_SRC_ARMV8_R_ARM_ARCH_TIMER_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include "arm_gic.h" -#include "arm_internal.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* CNTV_CVAL, Counter-timer Virtual Timer CompareValue register - * CNTV_CTL, Counter-timer Virtual Timer Control register - */ - -#define CNTV_CTL_ENABLE_BIT BIT(0) -#define CNTV_CTL_IMASK_BIT BIT(1) - -#define CONFIG_ARM_TIMER_SECURE_IRQ (GIC_PPI_INT_BASE + 13) -#define CONFIG_ARM_TIMER_NON_SECURE_IRQ (GIC_PPI_INT_BASE + 14) -#define CONFIG_ARM_TIMER_VIRTUAL_IRQ (GIC_PPI_INT_BASE + 11) -#define CONFIG_ARM_TIMER_HYP_IRQ (GIC_PPI_INT_BASE + 10) - -#define ARM_ARCH_TIMER_IRQ CONFIG_ARM_TIMER_VIRTUAL_IRQ -#define ARM_ARCH_TIMER_PRIO IRQ_DEFAULT_PRIORITY -#define ARM_ARCH_TIMER_FLAGS IRQ_TYPE_LEVEL - -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ -#ifdef CONFIG_SMP -void arm_arch_timer_secondary_init(void); -#endif - -#endif /* __ARCH_ARM_SRC_ARMV8_R_ARM_ARCH_TIMER_H */ diff --git a/arch/arm/src/armv8-r/arm_arch_timer.c b/arch/arm/src/armv8-r/arm_timer.c similarity index 82% rename from arch/arm/src/armv8-r/arm_arch_timer.c rename to arch/arm/src/armv8-r/arm_timer.c index 6ec70af6740df..3fa0638596b76 100644 --- a/arch/arm/src/armv8-r/arm_arch_timer.c +++ b/arch/arm/src/armv8-r/arm_timer.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/arm/src/armv8-r/arm_arch_timer.c + * arch/arm/src/armv8-r/arm_timer.c * * SPDX-License-Identifier: Apache-2.0 * @@ -30,14 +30,39 @@ #include #include +#include #include #include #include #include #include +#include +#include -#include "arm_gic.h" -#include "arm_arch_timer.h" +#include "arm_timer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CNT_CTL_ENABLE_BIT 0 +#define CNT_CTL_IMASK_BIT 1 +#define CNT_CTL_ISTATUS_BIT 2 + +#define GIC_IRQ_HYP_TIMER 26 /* Hypervisor Timer (HTM) IRQ */ +#define GIC_IRQ_VIRT_TIMER 27 /* Virtual Timer (VTM) IRQ */ +#define GIC_IRQ_SEC_PHY_TIMER 29 /* Secure Physical Timer IRQ */ +#define GIC_IRQ_NONSEC_PHY_TIMER 30 /* Non-secure Physical Timer IRQ */ + +#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) +# define GIC_IRQ_PHY_TIMER GIC_IRQ_SEC_PHY_TIMER +#else +# define GIC_IRQ_PHY_TIMER GIC_IRQ_NONSEC_PHY_TIMER +#endif + +#define ARM_ARCH_TIMER_IRQ GIC_IRQ_VIRT_TIMER +#define ARM_ARCH_TIMER_PRIO IRQ_DEFAULT_PRIORITY +#define ARM_ARCH_TIMER_FLAGS IRQ_TYPE_LEVEL /**************************************************************************** * Private Types @@ -64,60 +89,36 @@ struct arm_oneshot_lowerhalf_s * Private Functions ****************************************************************************/ -static inline void arm_arch_timer_set_compare(uint64_t value) +static inline void arm_timer_set_freq(uint32_t freq) { - CP15_SET64(CNTV_CVAL, value); + CP15_SET(CNTFRQ, freq); } -static inline uint64_t arm_arch_timer_get_compare(void) +static inline uint64_t arm_timer_phy_count(void) { - return CP15_GET64(CNTV_CVAL); + return CP15_GET64(CNTPCT); } -static inline void arm_arch_timer_enable(bool enable) +static inline void arm_timer_phy_set_relative(uint32_t tval) { - uint64_t value; - - value = CP15_GET(CNTV_CTL); - - if (enable) - { - value |= CNTV_CTL_ENABLE_BIT; - } - else - { - value &= ~CNTV_CTL_ENABLE_BIT; - } - - CP15_SET(CNTV_CTL, value); + CP15_SET(CNTP_TVAL, tval); } -static inline void arm_arch_timer_set_irq_mask(bool mask) +static inline void arm_timer_phy_set_absolute(uint64_t cval) { - uint64_t value; - - value = CP15_GET(CNTV_CTL); - - if (mask) - { - value |= CNTV_CTL_IMASK_BIT; - } - else - { - value &= ~CNTV_CTL_IMASK_BIT; - } - - CP15_SET(CNTV_CTL, value); + CP15_SET64(CNTP_CVAL, cval); } -static inline uint64_t arm_arch_timer_count(void) +static inline void arm_timer_phy_enable(bool enable) { - return CP15_GET64(CNTVCT); + CP15_MODIFY((uint32_t)enable << CNT_CTL_ENABLE_BIT, + BIT(CNT_CTL_ENABLE_BIT), CNTP_CTL); } -static inline uint64_t arm_arch_timer_get_cntfrq(void) +static inline void arm_timer_phy_set_irq_mask(bool mask) { - return CP15_GET(CNTFRQ); + CP15_MODIFY((uint32_t)mask << CNT_CTL_IMASK_BIT, + BIT(CNT_CTL_IMASK_BIT), CNTP_CTL); } /**************************************************************************** @@ -141,6 +142,10 @@ static int arm_arch_timer_compare_isr(int irq, void *regs, void *arg) struct arm_oneshot_lowerhalf_s *priv = (struct arm_oneshot_lowerhalf_s *)arg; + /* Suspend the timer irq, restart again when call tick_start */ + + arm_timer_phy_set_irq_mask(true); + if (priv->callback) { /* Then perform the callback */ @@ -212,7 +217,7 @@ static int arm_tick_cancel(struct oneshot_lowerhalf_s *lower, /* Disable int */ - arm_arch_timer_set_irq_mask(true); + arm_timer_phy_set_irq_mask(true); return OK; } @@ -253,14 +258,14 @@ static int arm_tick_start(struct oneshot_lowerhalf_s *lower, /* Set the timeout */ - arm_arch_timer_set_compare(arm_arch_timer_count() + - priv->cycle_per_tick * ticks); + arm_timer_phy_set_absolute(arm_timer_phy_count() + + priv->cycle_per_tick * ticks); /* Try to unmask the timer irq in timer controller * in case of arm_tick_cancel is called. */ - arm_arch_timer_set_irq_mask(false); + arm_timer_phy_set_irq_mask(false); return OK; } @@ -291,7 +296,7 @@ static int arm_tick_current(struct oneshot_lowerhalf_s *lower, DEBUGASSERT(ticks != NULL); - *ticks = arm_arch_timer_count() / priv->cycle_per_tick; + *ticks = arm_timer_phy_count() / priv->cycle_per_tick; return OK; } @@ -342,7 +347,7 @@ static struct oneshot_lowerhalf_s *arm_oneshot_initialize(void) /* Initialize the lower-half driver structure */ priv->lh.ops = &g_oneshot_ops; - priv->cycle_per_tick = arm_arch_timer_get_cntfrq() / TICK_PER_SEC; + priv->cycle_per_tick = arm_timer_get_freq() / TICK_PER_SEC; tmrinfo("cycle_per_tick %" PRIu64 "\n", priv->cycle_per_tick); /* Attach handler */ @@ -350,6 +355,10 @@ static struct oneshot_lowerhalf_s *arm_oneshot_initialize(void) irq_attach(ARM_ARCH_TIMER_IRQ, arm_arch_timer_compare_isr, priv); + /* Avoid early timer irq cause abort. */ + + arm_timer_phy_set_irq_mask(true); + tmrinfo("oneshot_initialize ok %p \n", &priv->lh); return &priv->lh; @@ -372,18 +381,18 @@ void up_timer_initialize(void) { uint64_t freq; - freq = arm_arch_timer_get_cntfrq(); + freq = arm_timer_get_freq(); tmrinfo("%s: cp15 timer(s) running at %" PRIu64 ".%" PRIu64 "MHz\n", __func__, freq / 1000000, (freq / 10000) % 100); up_alarm_set_lowerhalf(arm_oneshot_initialize()); up_enable_irq(ARM_ARCH_TIMER_IRQ); - arm_arch_timer_enable(true); + arm_timer_phy_enable(true); } #ifdef CONFIG_SMP /**************************************************************************** - * Function: arm_arch_timer_secondary_init + * Function: arm_timer_secondary_init * * Description: * This function is called during start-up to initialize the system timer @@ -402,7 +411,7 @@ void up_timer_initialize(void) * timer interrupt ****************************************************************************/ -void arm_arch_timer_secondary_init() +void arm_timer_secondary_init(void) { #ifdef CONFIG_SCHED_TICKLESS tmrinfo("arm_arch_timer_secondary_init\n"); @@ -413,7 +422,7 @@ void arm_arch_timer_secondary_init() /* Start timer */ - arm_arch_timer_enable(true); + arm_timer_phy_enable(true); #endif } #endif diff --git a/arch/arm64/src/goldfish/goldfish_timer.c b/arch/arm/src/armv8-r/arm_timer.h similarity index 79% rename from arch/arm64/src/goldfish/goldfish_timer.c rename to arch/arm/src/armv8-r/arm_timer.h index 2b6b9904f57f4..d97a2f0f87a24 100644 --- a/arch/arm64/src/goldfish/goldfish_timer.c +++ b/arch/arm/src/armv8-r/arm_timer.h @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/arm64/src/goldfish/goldfish_timer.c + * arch/arm/src/armv8-r/arm_timer.h * * SPDX-License-Identifier: Apache-2.0 * @@ -20,24 +20,22 @@ * ****************************************************************************/ +#ifndef __ARCH_ARM_SRC_ARMV8_R_ARM_TIMER_H +#define __ARCH_ARM_SRC_ARMV8_R_ARM_TIMER_H + /**************************************************************************** * Included Files ****************************************************************************/ -#include +#include +#include -#include "arm64_arch_timer.h" +#include /**************************************************************************** - * Public Functions + * Pre-processor Definitions ****************************************************************************/ -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} +#define arm_timer_get_freq() CP15_GET(CNTFRQ) -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} +#endif /* __ARCH_ARM_SRC_ARMV8_R_ARM_TIMER_H */ diff --git a/arch/arm/src/common/arm_internal.h b/arch/arm/src/common/arm_internal.h index a97c094e0afbe..ba105c7753ec4 100644 --- a/arch/arm/src/common/arm_internal.h +++ b/arch/arm/src/common/arm_internal.h @@ -463,6 +463,21 @@ void arm_netinitialize(void); # define arm_netinitialize() #endif +/**************************************************************************** + * Name: arm_timer_secondary_init + * + * Description: + * Initialize the ARM timer for secondary CPUs. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SMP +void arm_timer_secondary_init(unsigned int freq); +#endif + /* USB **********************************************************************/ #ifdef CONFIG_USBDEV diff --git a/arch/arm/src/goldfish/goldfish_cpuboot.c b/arch/arm/src/goldfish/goldfish_cpuboot.c index 90327f901c22f..7671e4be72c85 100644 --- a/arch/arm/src/goldfish/goldfish_cpuboot.c +++ b/arch/arm/src/goldfish/goldfish_cpuboot.c @@ -87,34 +87,9 @@ void arm_cpu_boot(int cpu) /* Initialize the Generic Interrupt Controller (GIC) for CPUn (n != 0) */ - arm_gic_initialize(); + up_irqinitialize(); -#ifdef CONFIG_ARCH_LOWVECTORS - /* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the - * beginning of the .text region must appear at address at the address - * specified in the VBAR. There are two ways to accomplish this: - * - * 1. By explicitly mapping the beginning of .text region with a page - * table entry so that the virtual address zero maps to the beginning - * of the .text region. VBAR == 0x0000:0000. - * - * 2. Set the Cortex-A5 VBAR register so that the vector table address - * is moved to a location other than 0x0000:0000. - * - * The second method is used by this logic. - */ - - /* Set the VBAR register to the address of the vector table */ - - DEBUGASSERT((((uintptr_t)_vector_start) & ~VBAR_MASK) == 0); - cp15_wrvbar((uint32_t)_vector_start); -#endif /* CONFIG_ARCH_LOWVECTORS */ - -#ifndef CONFIG_SUPPRESS_INTERRUPTS - /* And finally, enable interrupts */ - - up_irq_enable(); -#endif + arm_timer_secondary_init(0); /* The next thing that we expect to happen is for logic running on CPU0 * to call up_cpu_start() which generate an SGI and a context switch to diff --git a/arch/arm/src/imx6/imx_cpuboot.c b/arch/arm/src/imx6/imx_cpuboot.c index 2dc875fb479cb..5e13cd650032b 100644 --- a/arch/arm/src/imx6/imx_cpuboot.c +++ b/arch/arm/src/imx6/imx_cpuboot.c @@ -259,34 +259,7 @@ void arm_cpu_boot(int cpu) /* Initialize the Generic Interrupt Controller (GIC) for CPUn (n != 0) */ - arm_gic_initialize(); - -#ifdef CONFIG_ARCH_LOWVECTORS - /* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the - * beginning of the .text region must appear at address at the address - * specified in the VBAR. There are two ways to accomplish this: - * - * 1. By explicitly mapping the beginning of .text region with a page - * table entry so that the virtual address zero maps to the beginning - * of the .text region. VBAR == 0x0000:0000. - * - * 2. Set the Cortex-A5 VBAR register so that the vector table address - * is moved to a location other than 0x0000:0000. - * - * The second method is used by this logic. - */ - - /* Set the VBAR register to the address of the vector table */ - - DEBUGASSERT((((uintptr_t)_vector_start) & ~VBAR_MASK) == 0); - cp15_wrvbar((uint32_t)_vector_start); -#endif /* CONFIG_ARCH_LOWVECTORS */ - -#ifndef CONFIG_SUPPRESS_INTERRUPTS - /* And finally, enable interrupts */ - - up_irq_enable(); -#endif + up_irqinitialize(); /* The next thing that we expect to happen is for logic running on CPU0 * to call up_cpu_start() which generate an SGI and a context switch to diff --git a/arch/arm/src/qemu/qemu_cpuboot.c b/arch/arm/src/qemu/qemu_cpuboot.c index b92912f14b6d7..1b9457707ab71 100644 --- a/arch/arm/src/qemu/qemu_cpuboot.c +++ b/arch/arm/src/qemu/qemu_cpuboot.c @@ -81,34 +81,9 @@ void arm_cpu_boot(int cpu) /* Initialize the Generic Interrupt Controller (GIC) for CPUn (n != 0) */ - arm_gic_initialize(); - -#ifdef CONFIG_ARCH_LOWVECTORS - /* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the - * beginning of the .text region must appear at address at the address - * specified in the VBAR. There are two ways to accomplish this: - * - * 1. By explicitly mapping the beginning of .text region with a page - * table entry so that the virtual address zero maps to the beginning - * of the .text region. VBAR == 0x0000:0000. - * - * 2. Set the Cortex-A5 VBAR register so that the vector table address - * is moved to a location other than 0x0000:0000. - * - * The second method is used by this logic. - */ - - /* Set the VBAR register to the address of the vector table */ - - DEBUGASSERT((((uintptr_t)_vector_start) & ~VBAR_MASK) == 0); - cp15_wrvbar((uint32_t)_vector_start); -#endif /* CONFIG_ARCH_LOWVECTORS */ - -#ifndef CONFIG_SUPPRESS_INTERRUPTS - /* And finally, enable interrupts */ - - up_irq_enable(); -#endif + up_irqinitialize(); + + arm_timer_secondary_init(0); /* Then transfer control to the IDLE task */ diff --git a/arch/arm64/src/a527/CMakeLists.txt b/arch/arm64/src/a527/CMakeLists.txt index b3f842d71a993..c747f539b5bc4 100644 --- a/arch/arm64/src/a527/CMakeLists.txt +++ b/arch/arm64/src/a527/CMakeLists.txt @@ -19,7 +19,7 @@ # the License. # # ############################################################################## -set(SRCS a527_boot.c a527_serial.c a527_timer.c) +set(SRCS a527_boot.c a527_serial.c) if(CONFIG_ARCH_EARLY_PRINT) list(APPEND SRCS a527_lowputc.S) diff --git a/arch/arm64/src/a527/Make.defs b/arch/arm64/src/a527/Make.defs index ae1457020180c..188ae327a01fd 100644 --- a/arch/arm64/src/a527/Make.defs +++ b/arch/arm64/src/a527/Make.defs @@ -23,7 +23,7 @@ include common/Make.defs # C Source Files specific to SoC -CHIP_CSRCS = a527_boot.c a527_serial.c a527_timer.c +CHIP_CSRCS = a527_boot.c a527_serial.c ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) CHIP_ASRCS = a527_lowputc.S diff --git a/arch/arm64/src/a527/a527_timer.c b/arch/arm64/src/a527/a527_timer.c deleted file mode 100644 index 93550cade8032..0000000000000 --- a/arch/arm64/src/a527/a527_timer.c +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/a527/a527_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} diff --git a/arch/arm64/src/a64/Make.defs b/arch/arm64/src/a64/Make.defs index d704f15035422..ad87bcf71b24f 100644 --- a/arch/arm64/src/a64/Make.defs +++ b/arch/arm64/src/a64/Make.defs @@ -23,7 +23,7 @@ include common/Make.defs # Allwinner A64 specific C source files -CHIP_CSRCS = a64_boot.c a64_pio.c a64_serial.c a64_twi.c a64_timer.c +CHIP_CSRCS = a64_boot.c a64_pio.c a64_serial.c a64_twi.c ifeq ($(CONFIG_A64_DE),y) CHIP_CSRCS += a64_de.c diff --git a/arch/arm64/src/a64/a64_timer.c b/arch/arm64/src/a64/a64_timer.c deleted file mode 100644 index 9507a97773997..0000000000000 --- a/arch/arm64/src/a64/a64_timer.c +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/a64/a64_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/arm64/src/bcm2711/CMakeLists.txt b/arch/arm64/src/bcm2711/CMakeLists.txt index d8811d477a095..00c021def9e8a 100644 --- a/arch/arm64/src/bcm2711/CMakeLists.txt +++ b/arch/arm64/src/bcm2711/CMakeLists.txt @@ -20,8 +20,7 @@ # BCM2711 specific C source files -set(SRCS bcm2711_boot.c bcm2711_mailbox.c bcm2711_serial.c bcm2711_gpio.c - bcm2711_timer.c) +set(SRCS bcm2711_boot.c bcm2711_mailbox.c bcm2711_serial.c bcm2711_gpio.c) # Early boot logging diff --git a/arch/arm64/src/bcm2711/Make.defs b/arch/arm64/src/bcm2711/Make.defs index 4a7b5855eb7a2..b1e8e2608d773 100644 --- a/arch/arm64/src/bcm2711/Make.defs +++ b/arch/arm64/src/bcm2711/Make.defs @@ -26,7 +26,6 @@ CHIP_CSRCS += bcm2711_boot.c CHIP_CSRCS += bcm2711_mailbox.c CHIP_CSRCS += bcm2711_serial.c CHIP_CSRCS += bcm2711_gpio.c -CHIP_CSRCS += bcm2711_timer.c # Early boot logging diff --git a/arch/arm64/src/bcm2711/bcm2711_timer.c b/arch/arm64/src/bcm2711/bcm2711_timer.c deleted file mode 100644 index 6759d6f64ef48..0000000000000 --- a/arch/arm64/src/bcm2711/bcm2711_timer.c +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/bcm2711/bcm2711_timer.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/arm64/src/common/arm64_arch_timer.c b/arch/arm64/src/common/arm64_arch_timer.c index f1f5c7fae4c8c..3aac9b1615ff1 100644 --- a/arch/arm64/src/common/arm64_arch_timer.c +++ b/arch/arm64/src/common/arm64_arch_timer.c @@ -79,7 +79,7 @@ struct arm64_oneshot_lowerhalf_s }; /**************************************************************************** - * Private Functions + * Inline Functions ****************************************************************************/ static inline void arm64_arch_timer_set_compare(uint64_t value) @@ -135,66 +135,47 @@ static inline uint64_t arm64_arch_timer_get_cntfrq(void) static inline uint64_t arm64_arch_cnt2tick(uint64_t count, uint64_t freq) { - uint64_t multiply_safe_count = UINT64_MAX / TICK_PER_SEC; - uint64_t result_ticks = 0; - - /* We convert count to ticks via - * ticks = count / cycle_per_tick. - * Concretely, we have: - * ticks = count / (freq / TICK_PER_SEC). - * However, the `freq / TICK_PER_SEC` might be inaccurate - * due to the integer division. - * So we transform it to: - * ticks = count * TICK_PER_SEC / freq. + uint64_t sec; + uint64_t ticks; + + /* In case of count * TICK_PER_SEC overflow. + * We should divide the count into two parts: + * The second part and sub-second part. */ - if (count > multiply_safe_count) - { - /* In case of count * TICK_PER_SEC overflow. - * We divide the count into two parts: - * The multiply overflow part and non-overflow part. - * We convert the overflow part to ticks first, - * and then add the non-overflow part. - */ - - result_ticks += count / multiply_safe_count * - (multiply_safe_count * TICK_PER_SEC / freq); - count = count % multiply_safe_count; - } + sec = count / freq; + ticks = sec * TICK_PER_SEC; - /* Here we convert the non-overflow part to ticks. */ + /* Here we convert the sub-second part to ticks. */ - result_ticks += count * TICK_PER_SEC / freq; + count -= sec * freq; + ticks += count * TICK_PER_SEC / freq; - return result_ticks; + return ticks; } static inline uint64_t arm64_arch_tick2cnt(uint64_t ticks, uint64_t freq) { - uint64_t multiply_safe_ticks = UINT64_MAX / freq; - uint64_t result_count = 0; + uint64_t count; + uint64_t sec; - if (ticks > multiply_safe_ticks) - { - /* In case of count * freq overflow. - * We divide the ticks into two parts: - * The multiply overflow part and non-overflow part. - * We convert the overflow part to count first, - * and then add the non-overflow part. - */ - - result_count += ticks / multiply_safe_ticks * - (multiply_safe_ticks * freq / TICK_PER_SEC); - ticks = ticks % multiply_safe_ticks; - } + /* First we convert the second part to count. */ - /* Here we convert the non-overflow part to count. */ + sec = div_const(ticks, TICK_PER_SEC); + count = sec * freq; - result_count += ticks * freq / TICK_PER_SEC; + /* Here we convert the sub-second part to count. */ - return result_count; + ticks -= sec * TICK_PER_SEC; + count += div_const(ticks * freq, TICK_PER_SEC); + + return count; } +/**************************************************************************** + * Private Functions + ****************************************************************************/ + /**************************************************************************** * Name: arm64_arch_timer_compare_isr * @@ -334,7 +315,11 @@ static int arm64_tick_start(struct oneshot_lowerhalf_s *lower, priv->running = this_cpu(); - /* Align the timer count to the tick boundary */ + /* Align the timer count to the tick boundary. + * Notice that this is just a work-around. We should pass both + * the current system ticks and the delay ticks as input parameters. + * But we only have the delay tick here due to the oneshot interface. + */ next_tick = arm64_arch_cnt2tick(arm64_arch_timer_count(), freq) + ticks; next_cnt = arm64_arch_tick2cnt(next_tick, freq); @@ -351,15 +336,11 @@ static int arm64_tick_start(struct oneshot_lowerhalf_s *lower, * * Description: * Get the current time. - * - * Input Parameters: - * lower Caller allocated instance of the oneshot state structure. This * structure must have been previously initialized via a call to * oneshot_initialize(); * ticks The location in which to return the current time. * * Returned Value: - * Zero (OK) is returned on success, a negated errno value is returned on * any failure. * ****************************************************************************/ @@ -380,6 +361,28 @@ static int arm64_tick_current(struct oneshot_lowerhalf_s *lower, return OK; } +/**************************************************************************** + * Name: arm64_oneshot_initialize_per_cpu + * + * Description: + * Initialize the ARM generic timer for secondary CPUs. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void arm64_oneshot_initialize_per_cpu(void) +{ + /* Enable int */ + + up_enable_irq(ARM_ARCH_TIMER_IRQ); + + /* Start timer */ + + arm64_arch_timer_enable(true); +} + /**************************************************************************** * Private Data ****************************************************************************/ @@ -438,31 +441,19 @@ struct oneshot_lowerhalf_s *arm64_oneshot_initialize(void) irq_attach(ARM_ARCH_TIMER_IRQ, arm64_arch_timer_compare_isr, priv); - arm64_oneshot_secondary_init(); + arm64_oneshot_initialize_per_cpu(); tmrinfo("oneshot_initialize ok %p \n", &priv->lh); return &priv->lh; } -/**************************************************************************** - * Name: arm64_arch_timer_secondary_init - * - * Description: - * Initialize the ARM generic timer for secondary CPUs. - * - * Returned Value: - * None - * - ****************************************************************************/ - -void arm64_oneshot_secondary_init(void) +void up_timer_initialize(void) { - /* Enable int */ - - up_enable_irq(ARM_ARCH_TIMER_IRQ); - - /* Start timer */ + up_alarm_set_lowerhalf(arm64_oneshot_initialize()); +} - arm64_arch_timer_enable(true); +void arm64_timer_secondary_init(void) +{ + arm64_oneshot_initialize_per_cpu(); } diff --git a/arch/arm64/src/common/arm64_arch_timer.h b/arch/arm64/src/common/arm64_arch_timer.h index fd91d820ab5b5..0cfa433db965d 100644 --- a/arch/arm64/src/common/arm64_arch_timer.h +++ b/arch/arm64/src/common/arm64_arch_timer.h @@ -34,6 +34,7 @@ * Public Function Prototypes ****************************************************************************/ +#ifdef CONFIG_ONESHOT /**************************************************************************** * Name: arm64_oneshot_initialize * @@ -48,18 +49,6 @@ ****************************************************************************/ struct oneshot_lowerhalf_s *arm64_oneshot_initialize(void); - -/**************************************************************************** - * Name: arm64_oneshot_secondary_init - * - * Description: - * Initialize the ARM generic timer for secondary CPUs. - * - * Returned Value: - * None - * - ****************************************************************************/ - -void arm64_oneshot_secondary_init(void); +#endif #endif /* __ARCH_ARM64_SRC_COMMON_ARM64_ARCH_TIMER_H */ diff --git a/arch/arm64/src/common/arm64_boot.c b/arch/arm64/src/common/arm64_boot.c index 3ae06aaa52d05..480bfda740fe2 100644 --- a/arch/arm64/src/common/arm64_boot.c +++ b/arch/arm64/src/common/arm64_boot.c @@ -125,6 +125,10 @@ void arm64_boot_el2_init(void) { uint64_t reg; + /* Before we disable dcache, we should flush all dcache. */ + + up_flush_dcache_all(); + reg = 0U; /* RES0 */ reg = (SCTLR_EL2_RES1 | /* RES1 */ #ifndef CONFIG_ARM64_ICACHE_DISABLE @@ -196,6 +200,10 @@ void arm64_boot_el1_init(void) write_sysreg(reg, cpacr_el1); + /* Before we disable dcache, we should flush all dcache. */ + + up_flush_dcache_all(); + reg = 0U; /* RES0 */ reg = (SCTLR_EL1_RES1 | /* RES1 */ #ifndef CONFIG_ARM64_ICACHE_DISABLE diff --git a/arch/arm64/src/fvp-v8r/CMakeLists.txt b/arch/arm64/src/fvp-v8r/CMakeLists.txt index 8e41c3886313f..ead2d4f306368 100644 --- a/arch/arm64/src/fvp-v8r/CMakeLists.txt +++ b/arch/arm64/src/fvp-v8r/CMakeLists.txt @@ -17,7 +17,7 @@ # the License. # # ############################################################################## -set(SRCS fvp_boot.c fvp_serial.c fvp_timer.c) +set(SRCS fvp_boot.c fvp_serial.c) if(CONFIG_ARCH_EARLY_PRINT) list(APPEND SRCS fvp_lowputc.S) diff --git a/arch/arm64/src/fvp-v8r/Make.defs b/arch/arm64/src/fvp-v8r/Make.defs index b7895e40a5c79..b40eac0e01501 100644 --- a/arch/arm64/src/fvp-v8r/Make.defs +++ b/arch/arm64/src/fvp-v8r/Make.defs @@ -23,7 +23,7 @@ include common/Make.defs # fvp-specific C source files -CHIP_CSRCS = fvp_boot.c fvp_serial.c fvp_timer.c +CHIP_CSRCS = fvp_boot.c fvp_serial.c ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) CHIP_ASRCS += fvp_lowputc.S diff --git a/arch/arm64/src/fvp-v8r/fvp_timer.c b/arch/arm64/src/fvp-v8r/fvp_timer.c deleted file mode 100644 index 7076a4ec381d6..0000000000000 --- a/arch/arm64/src/fvp-v8r/fvp_timer.c +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/fvp-v8r/fvp_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/arm64/src/goldfish/CMakeLists.txt b/arch/arm64/src/goldfish/CMakeLists.txt index 0be4eddb20b40..ebe56f02e5418 100644 --- a/arch/arm64/src/goldfish/CMakeLists.txt +++ b/arch/arm64/src/goldfish/CMakeLists.txt @@ -19,7 +19,7 @@ # the License. # # ############################################################################## -set(SRCS goldfish_boot.c goldfish_serial.c goldfish_timer.c) +set(SRCS goldfish_boot.c goldfish_serial.c) if(CONFIG_RTC_PL031) list(APPEND SRCS goldfish_rtc.c) diff --git a/arch/arm64/src/goldfish/Make.defs b/arch/arm64/src/goldfish/Make.defs index 78e5bfcf6446c..2d864dbf444cd 100644 --- a/arch/arm64/src/goldfish/Make.defs +++ b/arch/arm64/src/goldfish/Make.defs @@ -23,7 +23,7 @@ include common/Make.defs # qemu-specific C source files -CHIP_CSRCS = goldfish_boot.c goldfish_serial.c goldfish_timer.c +CHIP_CSRCS = goldfish_boot.c goldfish_serial.c ifeq ($(CONFIG_RTC_PL031),y) CHIP_CSRCS += goldfish_rtc.c diff --git a/arch/arm64/src/imx8/Make.defs b/arch/arm64/src/imx8/Make.defs index aa1dd40c60023..725bec07afc12 100644 --- a/arch/arm64/src/imx8/Make.defs +++ b/arch/arm64/src/imx8/Make.defs @@ -24,7 +24,7 @@ include common/Make.defs # i.MX8-specific C source files -CHIP_CSRCS = imx8_boot.c imx8_timer.c +CHIP_CSRCS = imx8_boot.c ifeq ($(CONFIG_ARCH_CHIP_IMX8_QUADMAX),y) CHIP_CSRCS += imx8qm_serial.c diff --git a/arch/arm64/src/imx8/imx8_timer.c b/arch/arm64/src/imx8/imx8_timer.c deleted file mode 100644 index 2dcd454977467..0000000000000 --- a/arch/arm64/src/imx8/imx8_timer.c +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/imx8/imx8_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/arm64/src/imx9/Make.defs b/arch/arm64/src/imx9/Make.defs index 905fb00e0f66a..c8eab0dbd4293 100644 --- a/arch/arm64/src/imx9/Make.defs +++ b/arch/arm64/src/imx9/Make.defs @@ -28,7 +28,7 @@ endif # i.MX9-specific C source files -CHIP_CSRCS = imx9_boot.c imx9_timer.c +CHIP_CSRCS = imx9_boot.c ifeq ($(CONFIG_ARCH_CHIP_IMX93),y) CHIP_CSRCS += imx9_ccm.c imx9_gpio.c diff --git a/arch/arm64/src/imx9/imx9_timer.c b/arch/arm64/src/imx9/imx9_timer.c deleted file mode 100644 index 25458ab164cee..0000000000000 --- a/arch/arm64/src/imx9/imx9_timer.c +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/imx9/imx9_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/arm64/src/qemu/CMakeLists.txt b/arch/arm64/src/qemu/CMakeLists.txt index d48708feae79c..141673930a1a9 100644 --- a/arch/arm64/src/qemu/CMakeLists.txt +++ b/arch/arm64/src/qemu/CMakeLists.txt @@ -19,7 +19,7 @@ # the License. # # ############################################################################## -set(SRCS qemu_boot.c qemu_serial.c qemu_timer.c) +set(SRCS qemu_boot.c qemu_serial.c) if(CONFIG_ARCH_EARLY_PRINT) list(APPEND SRCS qemu_lowputc.S) diff --git a/arch/arm64/src/qemu/Make.defs b/arch/arm64/src/qemu/Make.defs index 8c24aeb582874..409b59d9e3f9a 100644 --- a/arch/arm64/src/qemu/Make.defs +++ b/arch/arm64/src/qemu/Make.defs @@ -25,8 +25,6 @@ include common/Make.defs # qemu-specific C source files CHIP_CSRCS = qemu_boot.c qemu_serial.c -CHIP_CSRCS += qemu_timer.c - ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) CHIP_ASRCS = qemu_lowputc.S endif diff --git a/arch/arm64/src/qemu/qemu_timer.c b/arch/arm64/src/qemu/qemu_timer.c deleted file mode 100644 index d663fec80030d..0000000000000 --- a/arch/arm64/src/qemu/qemu_timer.c +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/qemu/qemu_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/arm64/src/rk3399/Make.defs b/arch/arm64/src/rk3399/Make.defs index cc2f25c109e4e..138f4bd0d8025 100644 --- a/arch/arm64/src/rk3399/Make.defs +++ b/arch/arm64/src/rk3399/Make.defs @@ -23,7 +23,7 @@ include common/Make.defs # Rockchip RK3399 specific C source files -CHIP_CSRCS = rk3399_boot.c rk3399_serial.c rk3399_timer.c +CHIP_CSRCS = rk3399_boot.c rk3399_serial.c ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) CHIP_ASRCS = rk3399_lowputc.S diff --git a/arch/arm64/src/rk3399/rk3399_timer.c b/arch/arm64/src/rk3399/rk3399_timer.c deleted file mode 100644 index 29df447af2b69..0000000000000 --- a/arch/arm64/src/rk3399/rk3399_timer.c +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/rk3399/rk3399_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/arm64/src/zynq-mpsoc/Make.defs b/arch/arm64/src/zynq-mpsoc/Make.defs index cce3f7c6831da..b8781325ae2cd 100644 --- a/arch/arm64/src/zynq-mpsoc/Make.defs +++ b/arch/arm64/src/zynq-mpsoc/Make.defs @@ -23,7 +23,7 @@ include common/Make.defs # Rockchip zynq mpsoc specific C source files -CHIP_CSRCS = zynq_boot.c zynq_serial.c zynq_mio.c zynq_timer.c zynq_pll.c +CHIP_CSRCS = zynq_boot.c zynq_serial.c zynq_mio.c zynq_pll.c ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) CHIP_ASRCS = zynq_lowputc.S diff --git a/arch/arm64/src/zynq-mpsoc/zynq_timer.c b/arch/arm64/src/zynq-mpsoc/zynq_timer.c deleted file mode 100644 index f6296734758d7..0000000000000 --- a/arch/arm64/src/zynq-mpsoc/zynq_timer.c +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** - * arch/arm64/src/zynq-mpsoc/zynq_timer.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include "arm64_arch_timer.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -void up_timer_initialize(void) -{ - up_alarm_set_lowerhalf(arm64_oneshot_initialize()); -} - -void arm64_timer_secondary_init(void) -{ - arm64_oneshot_secondary_init(); -} diff --git a/arch/risc-v/src/common/riscv_mtimer.c b/arch/risc-v/src/common/riscv_mtimer.c index 4cbeeddd8abbb..52c6fab3122e5 100644 --- a/arch/risc-v/src/common/riscv_mtimer.c +++ b/arch/risc-v/src/common/riscv_mtimer.c @@ -28,11 +28,7 @@ #include #include -#include - -#include "riscv_internal.h" #include "riscv_mtimer.h" -#include "riscv_sbi.h" /**************************************************************************** * Private Types @@ -98,83 +94,16 @@ static const struct oneshot_operations_s g_riscv_mtimer_ops = * Private Functions ****************************************************************************/ -#ifndef CONFIG_ARCH_USE_S_MODE -static uint64_t riscv_mtimer_get_mtime(struct riscv_mtimer_lowerhalf_s *priv) -{ -#if CONFIG_ARCH_RV_MMIO_BITS == 64 - /* priv->mtime is -1, means this SoC: - * 1. does NOT support 64bit/DWORD write for the mtimer compare value regs, - * 2. has NO memory mapped regs which hold the value of mtimer counter, - * it could be read from the CSR "time". - */ - - return -1 == priv->mtime ? READ_CSR(CSR_TIME) : getreg64(priv->mtime); -#else - uint32_t hi; - uint32_t lo; - - do - { - hi = getreg32(priv->mtime + 4); - lo = getreg32(priv->mtime); - } - while (getreg32(priv->mtime + 4) != hi); - - return ((uint64_t)hi << 32) | lo; -#endif -} - -static void riscv_mtimer_set_mtimecmp(struct riscv_mtimer_lowerhalf_s *priv, - uint64_t value) -{ -#if CONFIG_ARCH_RV_MMIO_BITS == 64 - if (-1 != priv->mtime) - { - putreg64(value, priv->mtimecmp); - } - else -#endif - { - putreg32(UINT32_MAX, priv->mtimecmp + 4); - putreg32(value, priv->mtimecmp); - putreg32(value >> 32, priv->mtimecmp + 4); - } - - /* Make sure it sticks */ - - UP_DSB(); -} -#else - -#ifdef CONFIG_ARCH_RV_EXT_SSTC -static inline void riscv_write_stime(uint64_t value) -{ -#ifdef CONFIG_ARCH_RV64 - WRITE_CSR(CSR_STIMECMP, value); -#else - WRITE_CSR(CSR_STIMECMP, (uint32_t)value); - WRITE_CSR(CSR_STIMECMPH, (uint32_t)(value >> 32)); -#endif -} -#endif - static uint64_t riscv_mtimer_get_mtime(struct riscv_mtimer_lowerhalf_s *priv) { - UNUSED(priv); - return riscv_sbi_get_time(); + return riscv_mtimer_get(priv->mtime); } static void riscv_mtimer_set_mtimecmp(struct riscv_mtimer_lowerhalf_s *priv, uint64_t value) { - UNUSED(priv); -#ifndef CONFIG_ARCH_RV_EXT_SSTC - riscv_sbi_set_timer(value); -#else - riscv_write_stime(value); -#endif + riscv_mtimer_set(priv->mtime, priv->mtimecmp, value); } -#endif /**************************************************************************** * Name: riscv_mtimer_max_delay diff --git a/arch/risc-v/src/common/riscv_mtimer.h b/arch/risc-v/src/common/riscv_mtimer.h index a1d70805f315e..e30550f64a7ef 100644 --- a/arch/risc-v/src/common/riscv_mtimer.h +++ b/arch/risc-v/src/common/riscv_mtimer.h @@ -27,7 +27,97 @@ * Included Files ****************************************************************************/ +#include + #include +#include + +#include "riscv_internal.h" +#include "riscv_sbi.h" + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_USE_S_MODE +static inline uint64_t riscv_mtimer_get(uintreg_t mtime_addr) +{ +# if CONFIG_ARCH_RV_MMIO_BITS == 64 + /* mtime_addr is -1, means this SoC: + * 1. does NOT support 64bit/DWORD write for the mtimer compare value regs, + * 2. has NO memory mapped regs which hold the value of mtimer counter, + * it could be read from the CSR "time". + */ + + return -1 == mtime_addr ? READ_CSR(CSR_TIME) : getreg64(mtime_addr); +# else + uint32_t hi; + uint32_t lo; + + do + { + hi = getreg32(mtime_addr + 4); + lo = getreg32(mtime_addr); + } + while (getreg32(mtime_addr + 4) != hi); + + return ((uint64_t)hi << 32) | lo; +# endif +} + +static inline +void riscv_mtimer_set(uintreg_t mtime_addr, + uintreg_t mtimecmp_addr, uint64_t value) +{ +# if CONFIG_ARCH_RV_MMIO_BITS == 64 + if (-1 != mtime_addr) + { + putreg64(value, mtimecmp_addr); + } + else +# endif + { + putreg32(UINT32_MAX, mtimecmp_addr + 4); + putreg32(value, mtimecmp_addr); + putreg32(value >> 32, mtimecmp_addr + 4); + } + + UP_DSB(); +} + +#else + +# ifdef CONFIG_ARCH_RV_EXT_SSTC +static inline void riscv_write_stime(uint64_t value) +{ +# ifdef CONFIG_ARCH_RV64 + WRITE_CSR(CSR_STIMECMP, value); +# else + WRITE_CSR(CSR_STIMECMP, (uint32_t)value); + WRITE_CSR(CSR_STIMECMPH, (uint32_t)(value >> 32)); +# endif /* CONFIG_ARCH_RV64 */ +} +# endif /* CONFIG_ARCH_RV_EXT_SSTC */ + +static inline uint64_t riscv_mtimer_get(uintreg_t mtime_addr) +{ + UNUSED(mtime_addr); + return riscv_sbi_get_time(); +} + +static inline +void riscv_mtimer_set(uintreg_t mtime_addr, + uintreg_t mtimecmp_addr, uint64_t value) +{ + UNUSED(mtimecmp_addr); + UNUSED(mtime_addr); +# ifndef CONFIG_ARCH_RV_EXT_SSTC + riscv_sbi_set_timer(value); +# else + riscv_write_stime(value); +# endif /* CONFIG_ARCH_RV_EXT_SSTC */ +} +#endif /* CONFIG_ARCH_USE_S_MODE */ /**************************************************************************** * Public Function Prototypes diff --git a/arch/x86_64/include/intel64/arch.h b/arch/x86_64/include/intel64/arch.h index dd0051b04dd91..0364467ca47b6 100644 --- a/arch/x86_64/include/intel64/arch.h +++ b/arch/x86_64/include/intel64/arch.h @@ -269,6 +269,7 @@ # define MTRR_ENABLE 0x00000800 #define MSR_IA32_TSC_DEADLINE 0x6e0 +#define MSR_IA32_TSC_ADJUST 0x3b #define MSR_IA32_APIC_BASE 0x01b # define MSR_IA32_APIC_EN 0x800 diff --git a/arch/x86_64/src/intel64/Kconfig b/arch/x86_64/src/intel64/Kconfig index 7ea9fde9fef75..aac0c149fb3fd 100644 --- a/arch/x86_64/src/intel64/Kconfig +++ b/arch/x86_64/src/intel64/Kconfig @@ -21,6 +21,14 @@ endchoice # "Intel64 Chip Selection" config ARCH_INTEL64_HAVE_TSC bool +config ARCH_INTEL64_HAS_TSC_ADJUST + bool "MSR_IA32_TSC_ADJUST support" + depends on ARCH_INTEL64_HAVE_TSC + default y + ---help--- + MSR_IA32_TSC_ADJUST is used to adjust the offset of the Time Stamp Counter (TSC). + + config ARCH_INTEL64_CACHE_LINESIZE int "Cache line size (hardcoded)" depends on ARCH_DCACHE || ARCH_ICACHE diff --git a/arch/x86_64/src/intel64/intel64_cpustart.c b/arch/x86_64/src/intel64/intel64_cpustart.c index 466cc7710818e..baaf87ae99591 100644 --- a/arch/x86_64/src/intel64/intel64_cpustart.c +++ b/arch/x86_64/src/intel64/intel64_cpustart.c @@ -54,6 +54,7 @@ extern void __ap_entry(void); extern int x86_64_smp_call_handler(int irq, void *c, void *arg); extern int x86_64_smp_sched_handler(int irq, void *c, void *arg); +extern uint64_t get_tsc_adjust(void); /**************************************************************************** * Private Functions @@ -192,6 +193,8 @@ void x86_64_ap_boot(void) x86_64_stack_color(tcb->stack_alloc_ptr, 0); #endif + intel64_timer_secondary_init(); + /* CPU ready */ x86_64_cpu_ready_set(cpu); diff --git a/arch/x86_64/src/intel64/intel64_hpet_alarm.c b/arch/x86_64/src/intel64/intel64_hpet_alarm.c index e2a081c393e85..5240bcbaf508a 100644 --- a/arch/x86_64/src/intel64/intel64_hpet_alarm.c +++ b/arch/x86_64/src/intel64/intel64_hpet_alarm.c @@ -41,4 +41,9 @@ void up_timer_initialize(void) oneshot_initialize(CONFIG_ARCH_INTEL64_HPET_ALARM_CHAN, 10); up_alarm_set_lowerhalf(lower); } + +void intel64_timer_secondary_init(void) +{ + /* Secondary CPU initialization is not required. */ +} #endif diff --git a/arch/x86_64/src/intel64/intel64_lowsetup.h b/arch/x86_64/src/intel64/intel64_lowsetup.h index 844bd84f2417d..ab4539d4920cc 100644 --- a/arch/x86_64/src/intel64/intel64_lowsetup.h +++ b/arch/x86_64/src/intel64/intel64_lowsetup.h @@ -57,6 +57,16 @@ extern "C" void intel64_lowsetup(void); +/**************************************************************************** + * Name: intel64_timer_secondary_init + * + * Description: + * Called for the secondary CPUs to initialize the timer subsystem. + * + ****************************************************************************/ + +void intel64_timer_secondary_init(void); + #undef EXTERN #if defined(__cplusplus) } diff --git a/arch/x86_64/src/intel64/intel64_restore_auxstate.c b/arch/x86_64/src/intel64/intel64_restore_auxstate.c index f2c59fc8d9746..0639db45909f6 100644 --- a/arch/x86_64/src/intel64/intel64_restore_auxstate.c +++ b/arch/x86_64/src/intel64/intel64_restore_auxstate.c @@ -54,5 +54,7 @@ void x86_64_restore_auxstate(struct tcb_s *rtcb) { /* Set PCID, avoid TLB flush */ +#ifdef CONFIG_ARCH_INTEL64_HAVE_PCID set_pcid(rtcb->pid); +#endif } diff --git a/arch/x86_64/src/intel64/intel64_tsc_tickless.c b/arch/x86_64/src/intel64/intel64_tsc_tickless.c index c85e7c465a97f..1017725b410e4 100644 --- a/arch/x86_64/src/intel64/intel64_tsc_tickless.c +++ b/arch/x86_64/src/intel64/intel64_tsc_tickless.c @@ -58,8 +58,6 @@ #include #include -#ifdef CONFIG_SCHED_TICKLESS - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -78,23 +76,47 @@ extern unsigned long g_x86_64_timer_freq; -#ifndef CONFIG_SCHED_TICKLESS_ALARM +#ifdef CONFIG_SCHED_TICKLESS_ALARM +static struct timespec g_goal_time_ts; +#else static uint64_t g_goal_time; +#endif + +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_ADJUST +static uint64_t g_tsc_adjust; #else -static struct timespec g_goal_time_ts; +static uint64_t g_tsc_start; #endif -static uint64_t g_last_stop_time; -static uint64_t g_start_tsc; static uint32_t g_timer_active; static irqstate_t g_tmr_sync_count; static irqstate_t g_tmr_flags; +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_ADJUST +uint64_t get_tsc_adjust(void) +{ + return g_tsc_adjust; +} +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ +static inline uint64_t get_tsc_offset(void) +{ +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_ADJUST + return 0; +#else + return g_tsc_start; +#endif +} + void up_mask_tmr(void) { /* Disable TSC Deadline interrupt */ @@ -126,20 +148,33 @@ void up_unmask_tmr(void) __asm__ volatile("mfence" : : : "memory"); } -#ifndef CONFIG_SCHED_TICKLESS_ALARM -void up_timer_expire(void); -#else +#ifdef CONFIG_SCHED_TICKLESS_ALARM void up_alarm_expire(void); +#else +void up_timer_expire(void); #endif void up_timer_initialize(void) { - g_last_stop_time = g_start_tsc = rdtscp(); - -#ifndef CONFIG_SCHED_TICKLESS_ALARM - irq_attach(TMR_IRQ, (xcpt_t)up_timer_expire, NULL); + uint64_t tsc = rdtscp(); +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_ADJUST + g_tsc_adjust = read_msr(MSR_IA32_TSC_ADJUST) - tsc; + write_msr(MSR_IA32_TSC_ADJUST, g_tsc_adjust); #else + g_tsc_start = tsc; +#endif + +#ifdef CONFIG_SCHED_TICKLESS_ALARM irq_attach(TMR_IRQ, (xcpt_t)up_alarm_expire, NULL); +#else + irq_attach(TMR_IRQ, (xcpt_t)up_timer_expire, NULL); +#endif +} + +void intel64_timer_secondary_init(void) +{ +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_ADJUST + write_msr(MSR_IA32_TSC_ADJUST, get_tsc_adjust()); #endif } @@ -215,12 +250,12 @@ static inline void up_tmr_sync_down(void) int up_timer_gettime(struct timespec *ts) { - uint64_t diff = (rdtscp() - g_start_tsc); + uint64_t diff = rdtscp() - get_tsc_offset(); up_tick2ts(diff, ts); return OK; } -#ifndef CONFIG_SCHED_TICKLESS_ALARM +#ifdef CONFIG_SCHED_TICKLESS_ALARM /**************************************************************************** * Name: up_timer_cancel @@ -253,7 +288,7 @@ int up_timer_gettime(struct timespec *ts) * ****************************************************************************/ -int up_timer_cancel(struct timespec *ts) +int up_alarm_cancel(struct timespec *ts) { up_tmr_sync_up(); @@ -261,15 +296,7 @@ int up_timer_cancel(struct timespec *ts) if (ts != NULL) { - if (g_timer_active) - { - up_tick2ts(g_goal_time - rdtscp(), ts); - } - else - { - ts->tv_sec = 0; - ts->tv_nsec = 0; - } + up_timer_gettime(ts); } g_timer_active = 0; @@ -304,7 +331,7 @@ int up_timer_cancel(struct timespec *ts) * ****************************************************************************/ -int up_timer_start(const struct timespec *ts) +int up_alarm_start(const struct timespec *ts) { uint64_t ticks; @@ -312,20 +339,25 @@ int up_timer_start(const struct timespec *ts) up_unmask_tmr(); - ticks = up_ts2tick(ts) + rdtscp(); - - g_timer_active = 1; + ticks = up_ts2tick(ts) + get_tsc_offset(); write_msr(MSR_IA32_TSC_DEADLINE, ticks); - g_goal_time = ticks; + g_timer_active = 1; + + g_goal_time_ts.tv_sec = ts->tv_sec; + g_goal_time_ts.tv_nsec = ts->tv_nsec; up_tmr_sync_down(); + + tmrinfo("%" PRIdMAX ".%09ld\n", (uintmax_t)ts->tv_sec, ts->tv_nsec); + tmrinfo("start\n"); + return OK; } /**************************************************************************** - * Name: up_timer_expire + * Name: up_timer_update * * Description: * Called as the IRQ handler for alarm expiration. @@ -338,15 +370,21 @@ int up_timer_start(const struct timespec *ts) * ****************************************************************************/ -void up_timer_expire(void) +void up_alarm_expire(void) { - g_timer_active = 0; + struct timespec now; up_mask_tmr(); - nxsched_timer_expiration(); + tmrinfo("expire\n"); + + g_timer_active = 0; + + up_timer_gettime(&now); + + nxsched_alarm_expiration(&now); } -#else /* CONFIG_SCHED_TICKLESS_ALARM */ +#else /**************************************************************************** * Name: up_timer_cancel @@ -379,7 +417,7 @@ void up_timer_expire(void) * ****************************************************************************/ -int up_alarm_cancel(struct timespec *ts) +int up_timer_cancel(struct timespec *ts) { up_tmr_sync_up(); @@ -387,7 +425,15 @@ int up_alarm_cancel(struct timespec *ts) if (ts != NULL) { - up_timer_gettime(ts); + if (g_timer_active) + { + up_tick2ts(g_goal_time - rdtscp(), ts); + } + else + { + ts->tv_sec = 0; + ts->tv_nsec = 0; + } } g_timer_active = 0; @@ -422,7 +468,7 @@ int up_alarm_cancel(struct timespec *ts) * ****************************************************************************/ -int up_alarm_start(const struct timespec *ts) +int up_timer_start(const struct timespec *ts) { uint64_t ticks; @@ -430,25 +476,20 @@ int up_alarm_start(const struct timespec *ts) up_unmask_tmr(); - ticks = up_ts2tick(ts) + g_start_tsc; - - write_msr(MSR_IA32_TSC_DEADLINE, ticks); + ticks = up_ts2tick(ts) + rdtscp(); g_timer_active = 1; - g_goal_time_ts.tv_sec = ts->tv_sec; - g_goal_time_ts.tv_nsec = ts->tv_nsec; - - up_tmr_sync_down(); + write_msr(MSR_IA32_TSC_DEADLINE, ticks); - tmrinfo("%" PRIdMAX ".%09ld\n", (uintmax_t)ts->tv_sec, ts->tv_nsec); - tmrinfo("start\n"); + g_goal_time = ticks; + up_tmr_sync_down(); return OK; } /**************************************************************************** - * Name: up_timer_update + * Name: up_timer_expire * * Description: * Called as the IRQ handler for alarm expiration. @@ -461,19 +502,12 @@ int up_alarm_start(const struct timespec *ts) * ****************************************************************************/ -void up_alarm_expire(void) +void up_timer_expire(void) { - struct timespec now; - - up_mask_tmr(); - tmrinfo("expire\n"); - g_timer_active = 0; - up_timer_gettime(&now); - - nxsched_alarm_expiration(&now); + up_mask_tmr(); + nxsched_timer_expiration(); } #endif /* CONFIG_SCHED_TICKLESS_ALARM */ -#endif /* CONFIG_SCHED_TICKLESS */ diff --git a/arch/x86_64/src/intel64/intel64_tsc_timerisr.c b/arch/x86_64/src/intel64/intel64_tsc_timerisr.c index 81c0bfbeb7d28..b2dc70e435407 100644 --- a/arch/x86_64/src/intel64/intel64_tsc_timerisr.c +++ b/arch/x86_64/src/intel64/intel64_tsc_timerisr.c @@ -128,3 +128,8 @@ void up_timer_initialize(void) apic_timer_set(NS_PER_MSEC); } + +void intel64_timer_secondary_init(void) +{ + /* Secondary CPU initialization is not required. */ +}