diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index e62e4f4bd47..f4b01f8efd0 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -17,6 +17,8 @@ config ARCH_CHIP_FE310 select ARCH_RV_ISA_A select ARCH_RV_ISA_C select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- SiFive FE310 processor (E31 RISC-V Core with MAC extensions). @@ -34,6 +36,8 @@ config ARCH_CHIP_K210 select ARCH_HAVE_MULTICPU select ARCH_HAVE_MISALIGN_EXCEPTION select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- Kendryte K210 processor (RISC-V 64bit core with GC extensions) @@ -60,6 +64,8 @@ config ARCH_CHIP_BL602 select ARCH_HAVE_RESET select ARCH_HAVE_MISALIGN_EXCEPTION select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- BouffaloLab BL602(rv32imfc) @@ -194,6 +200,8 @@ config ARCH_CHIP_C906 select ARCH_HAVE_DPFPU select ARCH_HAVE_MPU select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- THEAD C906 processor (RISC-V 64bit core with GCVX extensions). @@ -219,6 +227,8 @@ config ARCH_CHIP_MPFS select ARCH_RV_CPUID_MAP select ARCH_HAVE_PERF_EVENTS select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- MicroChip Polarfire processor (RISC-V 64bit core with GCVX extensions). @@ -228,6 +238,10 @@ config ARCH_CHIP_RV32M1 select ARCH_RV32 select ARCH_RV_ISA_M select ARCH_RV_ISA_C + select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION + select ALARM_ARCH ---help--- NXP RV32M1 processor (RISC-V Core with PULP extensions). @@ -245,6 +259,8 @@ config ARCH_CHIP_QEMU_RV select ARCH_HAVE_S_MODE select ARCH_HAVE_ELF_EXECUTABLE select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH select ARCH_HAVE_DEBUG ---help--- @@ -257,6 +273,8 @@ config ARCH_CHIP_HPM6000 select ARCH_RV_ISA_A select ARCH_RV_ISA_C select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- Hpmicro HPM6000 processor (D45 RISC-V Core with MAC extensions). @@ -268,6 +286,8 @@ config ARCH_CHIP_HPM6750 select ARCH_RV_ISA_A select ARCH_RV_ISA_C select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- Hpmicro HPM6750 processor (D45 RISC-V Core with MAC extensions). @@ -287,6 +307,8 @@ config ARCH_CHIP_JH7110 select ARCH_NEED_ADDRENV_MAPPING select ARCH_HAVE_S_MODE select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- StarFive JH7110 SoC. @@ -307,6 +329,8 @@ config ARCH_CHIP_BL808 select ARCH_NEED_ADDRENV_MAPPING select ARCH_HAVE_S_MODE select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- Bouffalo Lab BL808 SoC. @@ -329,6 +353,8 @@ config ARCH_CHIP_K230 select ARCH_NEED_ADDRENV_MAPPING select NUTTSBI_LATE_INIT if NUTTSBI select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- Kendryte K230 SoC (RV64GCV and RV64GCVX C908 cores). @@ -349,6 +375,8 @@ config ARCH_CHIP_SG2000 select ARCH_NEED_ADDRENV_MAPPING select ARCH_HAVE_S_MODE select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- SOPHGO SG2000 SoC. @@ -368,6 +396,8 @@ config ARCH_CHIP_EIC7700X select ARCH_NEED_ADDRENV_MAPPING select ARCH_HAVE_S_MODE select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH ---help--- ESWIN EIC7700X SoC. @@ -384,6 +414,8 @@ config ARCH_CHIP_RP23XX_RV select ARCH_HAVE_I2CRESET select ARCH_HAVE_TICKLESS select ONESHOT + select ONESHOT_COUNT + select ONESHOT_FAST_DIVISION select ALARM_ARCH select ARCH_HAVE_I2CRESET select ARCH_BOARD_COMMON diff --git a/arch/risc-v/src/common/riscv_mtimer.c b/arch/risc-v/src/common/riscv_mtimer.c index 4e1a632ad02..ddd9d8bf744 100644 --- a/arch/risc-v/src/common/riscv_mtimer.c +++ b/arch/risc-v/src/common/riscv_mtimer.c @@ -44,22 +44,19 @@ struct riscv_mtimer_lowerhalf_s struct oneshot_lowerhalf_s lower; uintreg_t mtime; uintreg_t mtimecmp; - uint64_t freq; - uint64_t alarm; }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static int riscv_mtimer_max_delay(struct oneshot_lowerhalf_s *lower, - struct timespec *ts); -static int riscv_mtimer_start(struct oneshot_lowerhalf_s *lower, - const struct timespec *ts); -static int riscv_mtimer_cancel(struct oneshot_lowerhalf_s *lower, - struct timespec *ts); -static int riscv_mtimer_current(struct oneshot_lowerhalf_s *lower, - struct timespec *ts); +static clkcnt_t riscv_mtime_max_delay(struct oneshot_lowerhalf_s *lower); +static clkcnt_t riscv_mtime_current(struct oneshot_lowerhalf_s *lower); +static void riscv_mtime_start_absolute(struct oneshot_lowerhalf_s *lower, + clkcnt_t expected); +static void riscv_mtime_start(struct oneshot_lowerhalf_s *lower, + clkcnt_t delta); +static void riscv_mtime_cancel(struct oneshot_lowerhalf_s *lower); /**************************************************************************** * Private Data @@ -67,10 +64,16 @@ static int riscv_mtimer_current(struct oneshot_lowerhalf_s *lower, static const struct oneshot_operations_s g_riscv_mtimer_ops = { - .max_delay = riscv_mtimer_max_delay, - .start = riscv_mtimer_start, - .cancel = riscv_mtimer_cancel, - .current = riscv_mtimer_current, + .current = riscv_mtime_current, + .start = riscv_mtime_start, + .start_absolute = riscv_mtime_start_absolute, + .cancel = riscv_mtime_cancel, + .max_delay = riscv_mtime_max_delay +}; + +static struct riscv_mtimer_lowerhalf_s g_riscv_mtime_lowerhalf = +{ + .lower.ops = &g_riscv_mtimer_ops }; /**************************************************************************** @@ -88,167 +91,48 @@ static void riscv_mtimer_set_mtimecmp(struct riscv_mtimer_lowerhalf_s *priv, riscv_mtimer_set(priv->mtime, priv->mtimecmp, value); } -/**************************************************************************** - * Name: riscv_mtimer_max_delay - * - * Description: - * Determine the maximum delay of the one-shot timer - * - * Input Parameters: - * lower An instance of the lower-half oneshot state structure. This - * structure must have been previously initialized via a call to - * oneshot_initialize(); - * ts The location in which to return the maximum delay. - * - * Returned Value: - * Zero (OK) is returned on success; a negated errno value is returned - * on failure. - * - ****************************************************************************/ - -static int riscv_mtimer_max_delay(struct oneshot_lowerhalf_s *lower, - struct timespec *ts) +static clkcnt_t riscv_mtime_max_delay(struct oneshot_lowerhalf_s *lower) { - ts->tv_sec = UINT32_MAX; - ts->tv_nsec = NSEC_PER_SEC - 1; - - return 0; + return UINT64_MAX; } -/**************************************************************************** - * Name: riscv_mtimer_start - * - * Description: - * Start the oneshot timer - * - * Input Parameters: - * lower An instance of the lower-half oneshot state structure. This - * structure must have been previously initialized via a call to - * oneshot_initialize(); - * handler The function to call when when the oneshot timer expires. - * arg An opaque argument that will accompany the callback. - * ts Provides the duration of the one shot timer. - * - * Returned Value: - * Zero (OK) is returned on success; a negated errno value is returned - * on failure. - * - ****************************************************************************/ - -static int riscv_mtimer_start(struct oneshot_lowerhalf_s *lower, - const struct timespec *ts) +static clkcnt_t riscv_mtime_current(struct oneshot_lowerhalf_s *lower) { - struct riscv_mtimer_lowerhalf_s *priv = - (struct riscv_mtimer_lowerhalf_s *)lower; - irqstate_t flags; - uint64_t mtime; - uint64_t alarm; + struct riscv_mtimer_lowerhalf_s *priv = &g_riscv_mtime_lowerhalf; + return riscv_mtimer_get_mtime(priv); +} - flags = up_irq_save(); +static void riscv_mtime_start_absolute(struct oneshot_lowerhalf_s *lower, + clkcnt_t expected) +{ + struct riscv_mtimer_lowerhalf_s *priv = &g_riscv_mtime_lowerhalf; - mtime = riscv_mtimer_get_mtime(priv); - alarm = mtime + ts->tv_sec * priv->freq + - ts->tv_nsec * priv->freq / NSEC_PER_SEC; + riscv_mtimer_set_mtimecmp(priv, expected); +} - priv->alarm = alarm; +static void riscv_mtime_start(struct oneshot_lowerhalf_s *lower, + clkcnt_t delta) +{ + struct riscv_mtimer_lowerhalf_s *priv = &g_riscv_mtime_lowerhalf; + irqstate_t flags = up_irq_save(); + uint64_t curr = riscv_mtimer_get_mtime(priv); - riscv_mtimer_set_mtimecmp(priv, priv->alarm); + riscv_mtimer_set_mtimecmp(priv, curr + delta); up_irq_restore(flags); - return 0; } -/**************************************************************************** - * Name: riscv_mtimer_cancel - * - * Description: - * Cancel the oneshot timer and return the time remaining on the timer. - * - * NOTE: This function may execute at a high rate with no timer running (as - * when pre-emption is enabled and disabled). - * - * Input Parameters: - * lower Caller allocated instance of the oneshot state structure. This - * structure must have been previously initialized via a call to - * oneshot_initialize(); - * ts The location in which to return the time remaining on the - * oneshot timer. A time of zero is returned if the timer is - * not running. - * - * Returned Value: - * Zero (OK) is returned on success. A call to up_timer_cancel() when - * the timer is not active should also return success; a negated errno - * value is returned on any failure. - * - ****************************************************************************/ - -static int riscv_mtimer_cancel(struct oneshot_lowerhalf_s *lower, - struct timespec *ts) +static void riscv_mtime_cancel(struct oneshot_lowerhalf_s *lower) { - struct riscv_mtimer_lowerhalf_s *priv = - (struct riscv_mtimer_lowerhalf_s *)lower; - uint64_t mtime; - uint64_t alarm; - uint64_t nsec; - irqstate_t flags; - - flags = up_irq_save(); - - alarm = priv->alarm; - - mtime = riscv_mtimer_get_mtime(priv); - + struct riscv_mtimer_lowerhalf_s *priv = &g_riscv_mtime_lowerhalf; riscv_mtimer_set_mtimecmp(priv, UINT64_MAX); - - nsec = (alarm - mtime) * NSEC_PER_SEC / priv->freq; - ts->tv_sec = nsec / NSEC_PER_SEC; - ts->tv_nsec = nsec % NSEC_PER_SEC; - - priv->alarm = 0; - - up_irq_restore(flags); - - return 0; -} - -/**************************************************************************** - * Name: riscv_mtimer_current - * - * 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(); - * ts The location in which to return the current time. A time of zero - * is returned for the initialization moment. - * - * Returned Value: - * Zero (OK) is returned on success, a negated errno value is returned on - * any failure. - * - ****************************************************************************/ - -static int riscv_mtimer_current(struct oneshot_lowerhalf_s *lower, - struct timespec *ts) -{ - struct riscv_mtimer_lowerhalf_s *priv = - (struct riscv_mtimer_lowerhalf_s *)lower; - uint64_t mtime = riscv_mtimer_get_mtime(priv); - uint64_t left; - - ts->tv_sec = mtime / priv->freq; - left = mtime - ts->tv_sec * priv->freq; - ts->tv_nsec = NSEC_PER_SEC * left / priv->freq; - - return 0; } static int riscv_mtimer_interrupt(int irq, void *context, void *arg) { - struct riscv_mtimer_lowerhalf_s *priv = arg; + struct riscv_mtimer_lowerhalf_s *priv = &g_riscv_mtime_lowerhalf; + riscv_mtimer_set_mtimecmp(priv, UINT64_MAX); oneshot_process_callback(&priv->lower); return 0; @@ -262,21 +146,16 @@ struct oneshot_lowerhalf_s * riscv_mtimer_initialize(uintreg_t mtime, uintreg_t mtimecmp, int irq, uint64_t freq) { - struct riscv_mtimer_lowerhalf_s *priv; + struct riscv_mtimer_lowerhalf_s *priv = &g_riscv_mtime_lowerhalf; - priv = kmm_zalloc(sizeof(*priv)); - if (priv != NULL) - { - priv->lower.ops = &g_riscv_mtimer_ops; - priv->mtime = mtime; - priv->mtimecmp = mtimecmp; - priv->freq = freq; - priv->alarm = UINT64_MAX; + priv->mtime = mtime; + priv->mtimecmp = mtimecmp; - riscv_mtimer_set_mtimecmp(priv, priv->alarm); - irq_attach(irq, riscv_mtimer_interrupt, priv); - up_enable_irq(irq); - } + oneshot_count_init(&priv->lower, freq); - return (struct oneshot_lowerhalf_s *)priv; + riscv_mtimer_set_mtimecmp(priv, UINT64_MAX); + irq_attach(irq, riscv_mtimer_interrupt, priv); + up_enable_irq(irq); + + return &priv->lower; }