arch/intel64: add support for HPET as system clock
HPET can be used as system clock for x86_64 to set HPET as system clock you have to enable: CONFIG_ONESHOT=y CONFIG_ALARM_ARCH=y CONFIG_INTEL64_ONESHOT=y CONFIG_ARCH_INTEL64_HPET_ALARM=y Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
parent
c755218295
commit
3c05da536a
8 changed files with 309 additions and 4 deletions
|
@ -76,6 +76,10 @@ if(CONFIG_INTEL64_HPET)
|
|||
list(APPEND SRCS intel64_hpet.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_INTEL64_HPET_ALARM)
|
||||
list(APPEND SRCS intel64_hpet_alarm.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_INTEL64_ONESHOT)
|
||||
list(APPEND SRCS intel64_oneshot.c intel64_oneshot_lower.c)
|
||||
endif()
|
||||
|
|
|
@ -68,6 +68,14 @@ config ARCH_INTEL64_TSC
|
|||
---help---
|
||||
Select to enable the use of TSC APIC timer of x86_64
|
||||
|
||||
config ARCH_INTEL64_HPET_ALARM
|
||||
bool "HPET timer alarm support"
|
||||
depends on ALARM_ARCH
|
||||
---help---
|
||||
With this option you can enable ALARM_ARCH features that works on top of
|
||||
the HPET timer instance. This is an alternative method to TSC timer to
|
||||
provide the system clock.
|
||||
|
||||
endchoice # System Timer Source
|
||||
|
||||
if ARCH_INTEL64_TSC_DEADLINE
|
||||
|
@ -108,6 +116,11 @@ config INTEL64_HPET_BASE
|
|||
Configure base address for HPET. In the future, we can get this address from
|
||||
the ACPI table if ACPI support is enabled.
|
||||
|
||||
config ARCH_INTEL64_HPET_ALARM_CHAN
|
||||
int "HPET timer alarm channel"
|
||||
depends on ARCH_INTEL64_HPET_ALARM
|
||||
default 0
|
||||
|
||||
config INTEL64_HPET_CHANNELS
|
||||
int "HPET timer supported channels"
|
||||
default 2
|
||||
|
|
|
@ -66,6 +66,10 @@ ifeq ($(CONFIG_INTEL64_HPET),y)
|
|||
CHIP_CSRCS += intel64_hpet.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_INTEL64_HPET_ALARM),y)
|
||||
CHIP_CSRCS += intel64_hpet_alarm.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTEL64_ONESHOT),y)
|
||||
CHIP_CSRCS += intel64_oneshot.c intel64_oneshot_lower.c
|
||||
endif
|
||||
|
|
42
arch/x86_64/src/intel64/intel64_hpet_alarm.c
Normal file
42
arch/x86_64/src/intel64/intel64_hpet_alarm.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/****************************************************************************
|
||||
* arch/x86_64/src/intel64/intel64_hpet_alarm.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 <nuttx/config.h>
|
||||
|
||||
#include <nuttx/timers/arch_alarm.h>
|
||||
|
||||
#include "intel64_oneshot.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_INTEL64_HPET_ALARM
|
||||
void up_timer_initialize(void)
|
||||
{
|
||||
struct oneshot_lowerhalf_s *lower =
|
||||
oneshot_initialize(CONFIG_ARCH_INTEL64_HPET_ALARM_CHAN, 10);
|
||||
up_alarm_set_lowerhalf(lower);
|
||||
}
|
||||
#endif
|
|
@ -191,6 +191,12 @@ int intel64_oneshot_initialize(struct intel64_oneshot_s *oneshot, int chan,
|
|||
oneshot->period = INTEL64_TIM_GETPERIOD(oneshot->tch);
|
||||
oneshot->frequency = 1e15 / oneshot->period;
|
||||
|
||||
/* Calculations in intel64_oneshot_current() requires that HPET
|
||||
* frequency is less than 1GHz
|
||||
*/
|
||||
|
||||
DEBUGASSERT(oneshot->frequency < 1000000000);
|
||||
|
||||
/* Initialize the remaining fields in the state structure. */
|
||||
|
||||
oneshot->chan = chan;
|
||||
|
@ -423,3 +429,27 @@ int intel64_oneshot_cancel(struct intel64_oneshot_s *oneshot,
|
|||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: intel64_oneshot_current
|
||||
*
|
||||
* Description:
|
||||
* Get the current time.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int intel64_oneshot_current(struct intel64_oneshot_s *oneshot,
|
||||
uint64_t *usec)
|
||||
{
|
||||
uint64_t counter;
|
||||
|
||||
/* Get the current counter value */
|
||||
|
||||
counter = INTEL64_TIM_GETCOUNTER(oneshot->tch);
|
||||
|
||||
/* Use nano seconds to avoid 64-bit overflow */
|
||||
|
||||
*usec = (counter * (NSEC_PER_SEC / oneshot->frequency)) / 1000;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -168,6 +168,17 @@ int intel64_oneshot_start(struct intel64_oneshot_s *oneshot,
|
|||
int intel64_oneshot_cancel(struct intel64_oneshot_s *oneshot,
|
||||
struct timespec *ts);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: intel64_oneshot_current
|
||||
*
|
||||
* Description:
|
||||
* Get the current time.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int intel64_oneshot_current(struct intel64_oneshot_s *oneshot,
|
||||
uint64_t *usec);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
@ -64,6 +64,17 @@ static int intel64_start(struct oneshot_lowerhalf_s *lower,
|
|||
const struct timespec *ts);
|
||||
static int intel64_cancel(struct oneshot_lowerhalf_s *lower,
|
||||
struct timespec *ts);
|
||||
static int intel64_current(struct oneshot_lowerhalf_s *lower,
|
||||
struct timespec *ts);
|
||||
static int intel64_tick_max_delay(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks);
|
||||
static int intel64_tick_start(struct oneshot_lowerhalf_s *lower,
|
||||
oneshot_callback_t callback, void *arg,
|
||||
clock_t ticks);
|
||||
static int intel64_tick_cancel(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks);
|
||||
static int intel64_tick_current(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
|
@ -73,9 +84,14 @@ static int intel64_cancel(struct oneshot_lowerhalf_s *lower,
|
|||
|
||||
static const struct oneshot_operations_s g_oneshot_ops =
|
||||
{
|
||||
.max_delay = intel64_max_delay,
|
||||
.start = intel64_start,
|
||||
.cancel = intel64_cancel,
|
||||
.max_delay = intel64_max_delay,
|
||||
.start = intel64_start,
|
||||
.cancel = intel64_cancel,
|
||||
.current = intel64_current,
|
||||
.tick_max_delay = intel64_tick_max_delay,
|
||||
.tick_start = intel64_tick_start,
|
||||
.tick_cancel = intel64_tick_cancel,
|
||||
.tick_current = intel64_tick_current,
|
||||
};
|
||||
|
||||
static spinlock_t g_oneshotlow_spin;
|
||||
|
@ -268,6 +284,178 @@ static int intel64_cancel(struct oneshot_lowerhalf_s *lower,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: intel64_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();
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int intel64_current(struct oneshot_lowerhalf_s *lower,
|
||||
struct timespec *ts)
|
||||
{
|
||||
struct intel64_oneshot_lowerhalf_s *priv =
|
||||
(struct intel64_oneshot_lowerhalf_s *)lower;
|
||||
uint64_t current_us;
|
||||
|
||||
DEBUGASSERT(priv != NULL && ts != NULL);
|
||||
|
||||
intel64_oneshot_current(&priv->oneshot, ¤t_us);
|
||||
ts->tv_sec = current_us / USEC_PER_SEC;
|
||||
current_us = current_us - ts->tv_sec * USEC_PER_SEC;
|
||||
ts->tv_nsec = current_us * NSEC_PER_USEC;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: intel64_tick_max_delay
|
||||
*
|
||||
* Description:
|
||||
* Determine the maximum delay of the one-shot timer (in microseconds)
|
||||
*
|
||||
* 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();
|
||||
* ticks 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 intel64_tick_max_delay(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks)
|
||||
{
|
||||
struct timespec ts;
|
||||
int ret;
|
||||
|
||||
ret = intel64_max_delay(lower, &ts);
|
||||
|
||||
/* Convert time to ticks */
|
||||
|
||||
clock_time2ticks(&ts, (sclock_t *)ticks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: intel64_tick_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.
|
||||
* ticks 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 intel64_tick_start(struct oneshot_lowerhalf_s *lower,
|
||||
oneshot_callback_t callback, void *arg,
|
||||
clock_t ticks)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
/* Convert ticks to time */
|
||||
|
||||
clock_ticks2time(ticks, &ts);
|
||||
|
||||
return intel64_start(lower, callback, arg, &ts);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: intel64_tick_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();
|
||||
* ticks The location in which to return the time remaining on the
|
||||
* oneshot timer.
|
||||
*
|
||||
* 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 intel64_tick_cancel(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks)
|
||||
{
|
||||
struct timespec ts;
|
||||
int ret;
|
||||
|
||||
ret = intel64_cancel(lower, &ts);
|
||||
|
||||
/* Convert time to ticks */
|
||||
|
||||
clock_time2ticks(&ts, (sclock_t *)ticks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: intel64_tick_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();
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int intel64_tick_current(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks)
|
||||
{
|
||||
struct timespec ts;
|
||||
int ret;
|
||||
|
||||
ret = intel64_current(lower, &ts);
|
||||
|
||||
/* Convert time to ticks */
|
||||
|
||||
clock_time2ticks(&ts, (sclock_t *)ticks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
|
@ -39,6 +39,19 @@
|
|||
#include "x86_64_internal.h"
|
||||
#include "qemu_intel64.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_INTEL64_HPET_ALARM
|
||||
# if CONFIG_ARCH_INTEL64_HPET_ALARM_CHAN != 0
|
||||
# error this logic requires that HPET_ALARM_CHAN is set to 0
|
||||
# endif
|
||||
# define ONESHOT_TIMER 1
|
||||
#else
|
||||
# define ONESHOT_TIMER 0
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -72,7 +85,7 @@ int qemu_bringup(void)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_ONESHOT
|
||||
os = oneshot_initialize(0, 10);
|
||||
os = oneshot_initialize(ONESHOT_TIMER, 10);
|
||||
if (os)
|
||||
{
|
||||
oneshot_register("/dev/oneshot", os);
|
||||
|
|
Loading…
Reference in a new issue