Adapt HPET driver to work with QEMU
Qemu implements HPET so that it is connected to IRQ 2, which makes necessary to use it in legacy emulation mode. Add legacy emulation mode to HPET driver. Change the way the HPET driver is initialized. QEMU requires that the mode (one shot or periodic) gets set prior loading comparator value. Add debugging mode to HPET driver to ease the next port. Change-Id: I668325d5968451585519a08b6c41863cf6e37f88 Signed-off-by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com>
This commit is contained in:
parent
63fe84bdaf
commit
8b0271dd2c
3 changed files with 60 additions and 11 deletions
|
@ -41,6 +41,22 @@ config HPET_TIMER
|
|||
This option selects High Precision Event Timer (HPET) as a
|
||||
system timer.
|
||||
|
||||
config HPET_TIMER_LEGACY_EMULATION
|
||||
bool "HPET timer legacy emulation mode"
|
||||
default n
|
||||
depends on HPET_TIMER
|
||||
help
|
||||
This option switches HPET to legacy emulation mode.
|
||||
In this mode 8254 PIT is disabled, HPET timer0 is connected
|
||||
to IOAPIC IRQ2, timer1 -- to IOAPIC IRQ8.
|
||||
|
||||
config HPET_TIMER_DEBUG
|
||||
bool "Enable HPET debug output"
|
||||
default n
|
||||
depends on HPET_TIMER && PRINTK
|
||||
help
|
||||
This option enables HPET debugging output.
|
||||
|
||||
config LOAPIC_TIMER
|
||||
bool "LOAPIC timer"
|
||||
depends on LOAPIC && X86_32
|
||||
|
|
|
@ -204,6 +204,13 @@ static uint32_t main_count_expected_value = 0;
|
|||
extern uint32_t _hw_irq_to_c_handler_latency;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HPET_TIMER_DEBUG
|
||||
#include <misc/printk.h>
|
||||
#define PRINTK(...) printk(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTK(...)
|
||||
#endif
|
||||
|
||||
#ifdef TIMER_SUPPORTS_TICKLESS
|
||||
|
||||
/* additional globals, locals, and forward declarations */
|
||||
|
@ -546,33 +553,59 @@ int _sys_clock_driver_init(struct device *device)
|
|||
|
||||
counter_load_value = (uint32_t)(tickFempto / hpetClockPeriod);
|
||||
|
||||
PRINTK("\n\nHPET: configuration: 0x%x, clock period: 0x%x (%d pico-s)\n",
|
||||
(uint32_t)(*_HPET_GENERAL_CAPS),
|
||||
(uint32_t)hpetClockPeriod, (uint32_t)hpetClockPeriod / 1000);
|
||||
|
||||
PRINTK("HPET: timer0: available interrupts mask 0x%x\n",
|
||||
(uint32_t)(*_HPET_TIMER0_CONFIG_CAPS >> 32));
|
||||
|
||||
/* Initialize "sys_clock_hw_cycles_per_tick" */
|
||||
|
||||
sys_clock_hw_cycles_per_tick = counter_load_value;
|
||||
|
||||
/*
|
||||
* Set the comparator register for timer0. The write to the comparator
|
||||
* register is allowed due to setting the HPET_Tn_VAL_SET_CNF bit.
|
||||
*/
|
||||
|
||||
*_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF;
|
||||
*_HPET_TIMER0_COMPARATOR = counter_load_value;
|
||||
|
||||
#ifdef CONFIG_INT_LATENCY_BENCHMARK
|
||||
main_count_first_irq_value = counter_load_value;
|
||||
main_count_expected_value = main_count_first_irq_value;
|
||||
#endif
|
||||
|
||||
#ifndef TIMER_SUPPORTS_TICKLESS
|
||||
/* set timer0 to periodic mode, ready to expire every tick */
|
||||
#ifdef CONFIG_HPET_TIMER_LEGACY_EMULATION
|
||||
/*
|
||||
* Configure HPET replace legacy 8254 timer.
|
||||
* In this case the timer0 interrupt is routed to IRQ2
|
||||
* and legacy timer generates no interrupts
|
||||
*/
|
||||
*_HPET_GENERAL_CONFIG |= HPET_LEGACY_RT_CNF;
|
||||
#endif /* CONFIG_HPET_TIMER_LEGACY_EMULATION */
|
||||
|
||||
*_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_TYPE_CNF;
|
||||
#ifndef TIMER_SUPPORTS_TICKLESS
|
||||
/*
|
||||
* Set timer0 to periodic mode, ready to expire every tick
|
||||
* Setting 32-bit mode during the first load of the comparator
|
||||
* value is required to work around some hardware that otherwise
|
||||
* does not work properly.
|
||||
*/
|
||||
|
||||
*_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_TYPE_CNF | HPET_Tn_32MODE_CNF;
|
||||
#else
|
||||
/* set timer0 to one-shot mode, ready to expire on the first tick */
|
||||
|
||||
*_HPET_TIMER0_CONFIG_CAPS &= ~HPET_Tn_TYPE_CNF;
|
||||
#endif /* !TIMER_SUPPORTS_TICKLESS */
|
||||
|
||||
/*
|
||||
* Set the comparator register for timer0. The write to the comparator
|
||||
* register is allowed due to setting the HPET_Tn_VAL_SET_CNF bit.
|
||||
*/
|
||||
*_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF;
|
||||
*_HPET_TIMER0_COMPARATOR = counter_load_value;
|
||||
/*
|
||||
* After the comparator is loaded, 32-bit mode can be safely
|
||||
* switched off
|
||||
*/
|
||||
*_HPET_TIMER0_CONFIG_CAPS &= ~HPET_Tn_32MODE_CNF;
|
||||
|
||||
/*
|
||||
* Route interrupts to the I/O APIC. If HPET_Tn_INT_TYPE_CNF is set this
|
||||
* means edge triggered interrupt mode is utilized; Otherwise level
|
||||
|
|
|
@ -25,7 +25,7 @@ QEMU_BIOS ?= /usr/share/qemu
|
|||
QEMU_CPU_TYPE_x86 = qemu32
|
||||
QEMU_FLAGS_x86 = -m 32 -cpu $(QEMU_CPU_TYPE_x86) \
|
||||
-no-reboot -nographic -display none -net none \
|
||||
-clock dynticks -no-acpi -balloon none -no-hpet \
|
||||
-clock dynticks -no-acpi -balloon none \
|
||||
-L $(QEMU_BIOS) -bios bios.bin \
|
||||
-machine type=pc-0.14
|
||||
QEMU_x86 = qemu-system-i386
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue