// SPDX-License-Identifier: GPL-2.01/*2* 8253/PIT functions3*4*/5#include <linux/clockchips.h>6#include <linux/init.h>7#include <linux/timex.h>8#include <linux/i8253.h>910#include <asm/hypervisor.h>11#include <asm/apic.h>12#include <asm/hpet.h>13#include <asm/time.h>14#include <asm/smp.h>1516/*17* HPET replaces the PIT, when enabled. So we need to know, which of18* the two timers is used19*/20struct clock_event_device *global_clock_event;2122/*23* Modern chipsets can disable the PIT clock which makes it unusable. It24* would be possible to enable the clock but the registers are chipset25* specific and not discoverable. Avoid the whack a mole game.26*27* These platforms have discoverable TSC/CPU frequencies but this also28* requires to know the local APIC timer frequency as it normally is29* calibrated against the PIT interrupt.30*/31static bool __init use_pit(void)32{33if (!IS_ENABLED(CONFIG_X86_TSC) || !boot_cpu_has(X86_FEATURE_TSC))34return true;3536/* This also returns true when APIC is disabled */37return apic_needs_pit();38}3940bool __init pit_timer_init(void)41{42if (!use_pit()) {43/*44* Don't just ignore the PIT. Ensure it's stopped, because45* VMMs otherwise steal CPU time just to pointlessly waggle46* the (masked) IRQ.47*/48scoped_guard(irq)49clockevent_i8253_disable();50return false;51}52clockevent_i8253_init(true);53global_clock_event = &i8253_clockevent;54return true;55}5657#ifndef CONFIG_X86_6458static int __init init_pit_clocksource(void)59{60/*61* Several reasons not to register PIT as a clocksource:62*63* - On SMP PIT does not scale due to i8253_lock64* - when HPET is enabled65* - when local APIC timer is active (PIT is switched off)66*/67if (num_possible_cpus() > 1 || is_hpet_enabled() ||68!clockevent_state_periodic(&i8253_clockevent))69return 0;7071return clocksource_i8253_init();72}73arch_initcall(init_pit_clocksource);74#endif /* !CONFIG_X86_64 */757677