Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0 2 : /* 3 : * 8253/PIT functions 4 : * 5 : */ 6 : #include <linux/clockchips.h> 7 : #include <linux/init.h> 8 : #include <linux/timex.h> 9 : #include <linux/i8253.h> 10 : 11 : #include <asm/apic.h> 12 : #include <asm/hpet.h> 13 : #include <asm/time.h> 14 : #include <asm/smp.h> 15 : 16 : /* 17 : * HPET replaces the PIT, when enabled. So we need to know, which of 18 : * the two timers is used 19 : */ 20 : struct clock_event_device *global_clock_event; 21 : 22 : /* 23 : * Modern chipsets can disable the PIT clock which makes it unusable. It 24 : * would be possible to enable the clock but the registers are chipset 25 : * specific and not discoverable. Avoid the whack a mole game. 26 : * 27 : * These platforms have discoverable TSC/CPU frequencies but this also 28 : * requires to know the local APIC timer frequency as it normally is 29 : * calibrated against the PIT interrupt. 30 : */ 31 1 : static bool __init use_pit(void) 32 : { 33 1 : if (!IS_ENABLED(CONFIG_X86_TSC) || !boot_cpu_has(X86_FEATURE_TSC)) 34 : return true; 35 : 36 : /* This also returns true when APIC is disabled */ 37 1 : return apic_needs_pit(); 38 : } 39 : 40 1 : bool __init pit_timer_init(void) 41 : { 42 1 : if (!use_pit()) 43 : return false; 44 : 45 0 : clockevent_i8253_init(true); 46 0 : global_clock_event = &i8253_clockevent; 47 0 : return true; 48 : } 49 : 50 : #ifndef CONFIG_X86_64 51 : static int __init init_pit_clocksource(void) 52 : { 53 : /* 54 : * Several reasons not to register PIT as a clocksource: 55 : * 56 : * - On SMP PIT does not scale due to i8253_lock 57 : * - when HPET is enabled 58 : * - when local APIC timer is active (PIT is switched off) 59 : */ 60 : if (num_possible_cpus() > 1 || is_hpet_enabled() || 61 : !clockevent_state_periodic(&i8253_clockevent)) 62 : return 0; 63 : 64 : return clocksource_i8253_init(); 65 : } 66 : arch_initcall(init_pit_clocksource); 67 : #endif /* !CONFIG_X86_64 */