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:
Matt Borgerson 2016-08-03 23:05:18 -07:00
parent 635548482c
commit 81dd2188c4
5 changed files with 37 additions and 3 deletions

View File

@ -1,2 +1,2 @@
common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o
obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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 */