1 /* 2 * 8253/PIT functions 3 * 4 */ 5 #include <linux/clockchips.h> 6 #include <linux/interrupt.h> 7 #include <linux/spinlock.h> 8 #include <linux/jiffies.h> 9 #include <linux/module.h> 10 #include <linux/timex.h> 11 #include <linux/delay.h> 12 #include <linux/init.h> 13 #include <linux/io.h> 14 15 #include <asm/i8253.h> 16 #include <asm/hpet.h> 17 #include <asm/smp.h> 18 19 DEFINE_RAW_SPINLOCK(i8253_lock); 20 EXPORT_SYMBOL(i8253_lock); 21 22 /* 23 * HPET replaces the PIT, when enabled. So we need to know, which of 24 * the two timers is used 25 */ 26 struct clock_event_device *global_clock_event; 27 28 /* 29 * Initialize the PIT timer. 30 * 31 * This is also called after resume to bring the PIT into operation again. 32 */ 33 static void init_pit_timer(enum clock_event_mode mode, 34 struct clock_event_device *evt) 35 { 36 raw_spin_lock(&i8253_lock); 37 38 switch (mode) { 39 case CLOCK_EVT_MODE_PERIODIC: 40 /* binary, mode 2, LSB/MSB, ch 0 */ 41 outb_pit(0x34, PIT_MODE); 42 outb_pit(LATCH & 0xff , PIT_CH0); /* LSB */ 43 outb_pit(LATCH >> 8 , PIT_CH0); /* MSB */ 44 break; 45 46 case CLOCK_EVT_MODE_SHUTDOWN: 47 case CLOCK_EVT_MODE_UNUSED: 48 if (evt->mode == CLOCK_EVT_MODE_PERIODIC || 49 evt->mode == CLOCK_EVT_MODE_ONESHOT) { 50 outb_pit(0x30, PIT_MODE); 51 outb_pit(0, PIT_CH0); 52 outb_pit(0, PIT_CH0); 53 } 54 break; 55 56 case CLOCK_EVT_MODE_ONESHOT: 57 /* One shot setup */ 58 outb_pit(0x38, PIT_MODE); 59 break; 60 61 case CLOCK_EVT_MODE_RESUME: 62 /* Nothing to do here */ 63 break; 64 } 65 raw_spin_unlock(&i8253_lock); 66 } 67 68 /* 69 * Program the next event in oneshot mode 70 * 71 * Delta is given in PIT ticks 72 */ 73 static int pit_next_event(unsigned long delta, struct clock_event_device *evt) 74 { 75 raw_spin_lock(&i8253_lock); 76 outb_pit(delta & 0xff , PIT_CH0); /* LSB */ 77 outb_pit(delta >> 8 , PIT_CH0); /* MSB */ 78 raw_spin_unlock(&i8253_lock); 79 80 return 0; 81 } 82 83 /* 84 * On UP the PIT can serve all of the possible timer functions. On SMP systems 85 * it can be solely used for the global tick. 86 * 87 * The profiling and update capabilities are switched off once the local apic is 88 * registered. This mechanism replaces the previous #ifdef LOCAL_APIC - 89 * !using_apic_timer decisions in do_timer_interrupt_hook() 90 */ 91 static struct clock_event_device pit_ce = { 92 .name = "pit", 93 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 94 .set_mode = init_pit_timer, 95 .set_next_event = pit_next_event, 96 .irq = 0, 97 }; 98 99 /* 100 * Initialize the conversion factor and the min/max deltas of the clock event 101 * structure and register the clock event source with the framework. 102 */ 103 void __init setup_pit_timer(void) 104 { 105 /* 106 * Start pit with the boot cpu mask and make it global after the 107 * IO_APIC has been initialized. 108 */ 109 pit_ce.cpumask = cpumask_of(smp_processor_id()); 110 111 clockevents_config_and_register(&pit_ce, CLOCK_TICK_RATE, 0xF, 0x7FFF); 112 global_clock_event = &pit_ce; 113 } 114 115 #ifndef CONFIG_X86_64 116 static int __init init_pit_clocksource(void) 117 { 118 /* 119 * Several reasons not to register PIT as a clocksource: 120 * 121 * - On SMP PIT does not scale due to i8253_lock 122 * - when HPET is enabled 123 * - when local APIC timer is active (PIT is switched off) 124 */ 125 if (num_possible_cpus() > 1 || is_hpet_enabled() || 126 pit_ce.mode != CLOCK_EVT_MODE_PERIODIC) 127 return 0; 128 129 return clocksource_i8253_init(); 130 } 131 arch_initcall(init_pit_clocksource); 132 #endif /* !CONFIG_X86_64 */ 133