mirror of https://github.com/xemu-project/xemu.git
Make the ACPI PM timer more hardware accurate
On the Xbox, the ACPI PM timer is a 32-bit counter which runs at 3.375 MHz. This timer may be sampled via the KeQueryPerformanceCounter and KeQueryPerformanceFrequency kernel functions.
This commit is contained in:
parent
635548482c
commit
81dd2188c4
|
@ -1,2 +1,2 @@
|
|||
common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o
|
||||
obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o
|
||||
|
||||
|
|
|
@ -482,13 +482,21 @@ void acpi_pm_tmr_update(ACPIREGS *ar, bool enable)
|
|||
void acpi_pm_tmr_calc_overflow_time(ACPIREGS *ar)
|
||||
{
|
||||
int64_t d = acpi_pm_tmr_get_clock();
|
||||
#ifdef TARGET_XBOX
|
||||
ar->tmr.overflow_time = (d + 0x80000000LL) & ~0x7fffffffLL;
|
||||
#else
|
||||
ar->tmr.overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t acpi_pm_tmr_get(ACPIREGS *ar)
|
||||
{
|
||||
uint32_t d = acpi_pm_tmr_get_clock();
|
||||
#ifdef TARGET_XBOX
|
||||
return d & 0xffffffff;
|
||||
#else
|
||||
return d & 0xffffff;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void acpi_pm_tmr_timer(void *opaque)
|
||||
|
|
|
@ -492,6 +492,9 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm)
|
|||
(1 << ACPI_FADT_F_SLP_BUTTON) |
|
||||
(1 << ACPI_FADT_F_RTC_S4));
|
||||
fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_USE_PLATFORM_CLOCK);
|
||||
#ifdef TARGET_XBOX
|
||||
fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_TMR_VAL_EXT);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -72,10 +72,29 @@ static const MemoryRegionOps xbox_pm_gpio_ops = {
|
|||
.write = xbox_pm_gpio_write,
|
||||
};
|
||||
|
||||
static void pm_update_sci(XBOX_PMRegs *pm)
|
||||
{
|
||||
int sci_level, pm1a_sts;
|
||||
|
||||
pm1a_sts = acpi_pm1_evt_get_sts(&pm->acpi_regs);
|
||||
|
||||
sci_level = (((pm1a_sts & pm->acpi_regs.pm1.evt.en) &
|
||||
(ACPI_BITMASK_RT_CLOCK_ENABLE |
|
||||
ACPI_BITMASK_POWER_BUTTON_ENABLE |
|
||||
ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
|
||||
ACPI_BITMASK_TIMER_ENABLE)) != 0);
|
||||
qemu_set_irq(pm->irq, sci_level);
|
||||
|
||||
/* schedule a timer interruption if needed */
|
||||
acpi_pm_tmr_update(&pm->acpi_regs,
|
||||
(pm->acpi_regs.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
|
||||
!(pm1a_sts & ACPI_BITMASK_TIMER_STATUS));
|
||||
}
|
||||
|
||||
static void xbox_pm_update_sci_fn(ACPIREGS *regs)
|
||||
{
|
||||
//XBOX_PMRegs *pm = container_of(regs, XBOX_PMRegs, acpi_regs);
|
||||
//pm_update_sci(pm);
|
||||
XBOX_PMRegs *pm = container_of(regs, XBOX_PMRegs, acpi_regs);
|
||||
pm_update_sci(pm);
|
||||
}
|
||||
|
||||
#define XBOX_PM_BASE_BAR 0
|
||||
|
|
|
@ -34,7 +34,11 @@
|
|||
#define ACPI_PM_TIMER_WIDTH 32
|
||||
|
||||
/* PM Timer ticks per second (HZ) */
|
||||
#ifdef TARGET_XBOX
|
||||
#define PM_TIMER_FREQUENCY 3375000
|
||||
#else
|
||||
#define PM_TIMER_FREQUENCY 3579545
|
||||
#endif
|
||||
|
||||
|
||||
/* ACPI fixed hardware registers */
|
||||
|
|
Loading…
Reference in New Issue