mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
arch/risc-v: Add clkdev driver for mtime.
This commit added clkdev driver for risc-v machine timer. Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit is contained in:
parent
b2fc959e40
commit
2227f232f0
2 changed files with 81 additions and 170 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue