mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Revert "x86/timer: Fix boot on Intel systems using ITSSPRC static PIT clock gating"
This reverts commit c11bd12218,
as it has been reported to cause symptoms similar to what it
fixes on other hardware.
This commit is contained in:
1 parent
015e51a0bc
commit
53e83edb8d
1 file changed
+1
-66
+1
-66
@@ -767,7 +767,7 @@ static u32 *hpet_boot_cfg;
|
||||
u64 __init hpet_setup(void)
|
||||
{
|
||||
static u64 __initdata hpet_rate;
|
||||
unsigned int hpet_id, hpet_period, hpet_cfg;
|
||||
u32 hpet_id, hpet_period;
|
||||
unsigned int last;
|
||||
|
||||
if ( hpet_rate )
|
||||
@@ -800,71 +800,6 @@ u64 __init hpet_setup(void)
|
||||
hpet_rate = 1000000000000000ULL; /* 10^15 */
|
||||
(void)do_div(hpet_rate, hpet_period);
|
||||
|
||||
/*
|
||||
* Intel chipsets from Skylake/ApolloLake onwards can statically clock
|
||||
* gate the 8259 PIT. This option is enabled by default in slightly later
|
||||
* systems, as turning the PIT off is a prerequisite to entering the C11
|
||||
* power saving state.
|
||||
*
|
||||
* Xen currently depends on the legacy timer interrupt being active while
|
||||
* IRQ routing is configured.
|
||||
*
|
||||
* Reconfigure the HPET into legacy mode to re-establish the timer
|
||||
* interrupt.
|
||||
*/
|
||||
if ( hpet_id & HPET_ID_LEGSUP &&
|
||||
!((hpet_cfg = hpet_read32(HPET_CFG)) & HPET_CFG_LEGACY) )
|
||||
{
|
||||
unsigned int c0_cfg, ticks, count;
|
||||
|
||||
/* Stop the main counter. */
|
||||
hpet_write32(hpet_cfg & ~HPET_CFG_ENABLE, HPET_CFG);
|
||||
|
||||
/* Reconfigure channel 0 to be 32bit periodic. */
|
||||
c0_cfg = hpet_read32(HPET_Tn_CFG(0));
|
||||
c0_cfg |= (HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
|
||||
HPET_TN_32BIT);
|
||||
hpet_write32(c0_cfg, HPET_Tn_CFG(0));
|
||||
|
||||
/*
|
||||
* The exact period doesn't have to match a legacy PIT. All we need
|
||||
* is an interrupt queued up via the IO-APIC to check routing.
|
||||
*
|
||||
* Use HZ as the frequency.
|
||||
*/
|
||||
ticks = ((SECONDS(1) / HZ) * div_sc(hpet_rate, SECONDS(1), 32)) >> 32;
|
||||
|
||||
count = hpet_read32(HPET_COUNTER);
|
||||
|
||||
/*
|
||||
* HPET_TN_SETVAL above is atrociously documented in the spec.
|
||||
*
|
||||
* Periodic HPET channels have a main comparator register, and
|
||||
* separate "accumulator" register. Despite being named accumulator
|
||||
* in the spec, this is not an accurate description of its behaviour
|
||||
* or purpose.
|
||||
*
|
||||
* Each time an interrupt is generated, the "accumulator" register is
|
||||
* re-added to the comparator set up the new period.
|
||||
*
|
||||
* Normally, writes to the CMP register update both registers.
|
||||
* However, under these semantics, it is impossible to set up a
|
||||
* periodic timer correctly without the main HPET counter being at 0.
|
||||
*
|
||||
* Instead, HPET_TN_SETVAL is a self-clearing control bit which we can
|
||||
* use for periodic timers to mean that the second write to CMP
|
||||
* updates the accumulator only, and not the absolute comparator
|
||||
* value.
|
||||
*
|
||||
* This lets us set a period when the main counter isn't at 0.
|
||||
*/
|
||||
hpet_write32(count + ticks, HPET_Tn_CMP(0));
|
||||
hpet_write32(ticks, HPET_Tn_CMP(0));
|
||||
|
||||
/* Restart the main counter, and legacy mode. */
|
||||
hpet_write32(hpet_cfg | HPET_CFG_ENABLE | HPET_CFG_LEGACY, HPET_CFG);
|
||||
}
|
||||
|
||||
return hpet_rate;
|
||||
}
|
||||
|
||||
|
||||