Skip to content

Commit

Permalink
Make the ACPI PM timer more hardware accurate
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mborgerson committed Aug 4, 2016
1 parent 6355484 commit 81dd218
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 3 deletions.
2 changes: 1 addition & 1 deletion hw/acpi/Makefile.objs
@@ -1,2 +1,2 @@
common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o
obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o

8 changes: 8 additions & 0 deletions hw/acpi/core.c
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions hw/i386/acpi-build.c
Expand Up @@ -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
}


Expand Down
23 changes: 21 additions & 2 deletions hw/xbox/acpi_xbox.c
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions include/hw/acpi/acpi.h
Expand Up @@ -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 */
Expand Down

0 comments on commit 81dd218

Please sign in to comment.