1/* 2 * VMI paravirtual timer support routines. 3 * 4 * Copyright (C) 2007, VMware, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 14 * NON INFRINGEMENT. See the GNU General Public License for more 15 * details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * 21 */ 22 23#include <linux/smp.h> 24#include <linux/interrupt.h> 25#include <linux/cpumask.h> 26#include <linux/clocksource.h> 27#include <linux/clockchips.h> 28 29#include <asm/vmi.h> 30#include <asm/vmi_time.h> 31#include <asm/arch_hooks.h> 32#include <asm/apicdef.h> 33#include <asm/apic.h> 34#include <asm/timer.h> 35 36#include <irq_vectors.h> 37#include "io_ports.h" 38 39#define VMI_ONESHOT (VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL | vmi_get_alarm_wiring()) 40#define VMI_PERIODIC (VMI_ALARM_IS_PERIODIC | VMI_CYCLES_REAL | vmi_get_alarm_wiring()) 41 42static DEFINE_PER_CPU(struct clock_event_device, local_events); 43 44static inline u32 vmi_counter(u32 flags) 45{ 46 /* Given VMI_ONESHOT or VMI_PERIODIC, return the corresponding 47 * cycle counter. */ 48 return flags & VMI_ALARM_COUNTER_MASK; 49} 50 51/* paravirt_ops.get_wallclock = vmi_get_wallclock */ 52unsigned long vmi_get_wallclock(void) 53{ 54 unsigned long long wallclock; 55 wallclock = vmi_timer_ops.get_wallclock(); // nsec 56 (void)do_div(wallclock, 1000000000); // sec 57 58 return wallclock; 59} 60 61/* paravirt_ops.set_wallclock = vmi_set_wallclock */ 62int vmi_set_wallclock(unsigned long now) 63{ 64 return 0; 65} 66 67/* paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles */ 68unsigned long long vmi_get_sched_cycles(void) 69{ 70 return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE); 71} 72 73/* paravirt_ops.get_cpu_khz = vmi_cpu_khz */ 74unsigned long vmi_cpu_khz(void) 75{ 76 unsigned long long khz; 77 khz = vmi_timer_ops.get_cycle_frequency(); 78 (void)do_div(khz, 1000); 79 return khz; 80} 81 82static inline unsigned int vmi_get_timer_vector(void) 83{ 84#ifdef CONFIG_X86_IO_APIC 85 return FIRST_DEVICE_VECTOR; 86#else 87 return FIRST_EXTERNAL_VECTOR; 88#endif 89} 90 91/** vmi clockchip */ 92#ifdef CONFIG_X86_LOCAL_APIC 93static unsigned int startup_timer_irq(unsigned int irq) 94{ 95 unsigned long val = apic_read(APIC_LVTT); 96 apic_write(APIC_LVTT, vmi_get_timer_vector()); 97 98 return (val & APIC_SEND_PENDING); 99} 100 101static void mask_timer_irq(unsigned int irq) 102{ 103 unsigned long val = apic_read(APIC_LVTT); 104 apic_write(APIC_LVTT, val | APIC_LVT_MASKED); 105} 106 107static void unmask_timer_irq(unsigned int irq) 108{ 109 unsigned long val = apic_read(APIC_LVTT); 110 apic_write(APIC_LVTT, val & ~APIC_LVT_MASKED); 111} 112 113static void ack_timer_irq(unsigned int irq) 114{ 115 ack_APIC_irq(); 116} 117 118static struct irq_chip vmi_chip __read_mostly = { 119 .name = "VMI-LOCAL", 120 .startup = startup_timer_irq, 121 .mask = mask_timer_irq, 122 .unmask = unmask_timer_irq, 123 .ack = ack_timer_irq 124}; 125#endif 126 127/** vmi clockevent */ 128#define VMI_ALARM_WIRED_IRQ0 0x00000000 129#define VMI_ALARM_WIRED_LVTT 0x00010000 130static int vmi_wiring = VMI_ALARM_WIRED_IRQ0; 131 132static inline int vmi_get_alarm_wiring(void) 133{ 134 return vmi_wiring; 135} 136 137static void vmi_timer_set_mode(enum clock_event_mode mode, 138 struct clock_event_device *evt) 139{ 140 cycle_t now, cycles_per_hz; 141 BUG_ON(!irqs_disabled()); 142 143 switch (mode) { 144 case CLOCK_EVT_MODE_ONESHOT: 145 break; 146 case CLOCK_EVT_MODE_PERIODIC: 147 cycles_per_hz = vmi_timer_ops.get_cycle_frequency(); 148 (void)do_div(cycles_per_hz, HZ); 149 now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_PERIODIC)); 150 vmi_timer_ops.set_alarm(VMI_PERIODIC, now, cycles_per_hz); 151 break; 152 case CLOCK_EVT_MODE_UNUSED: 153 case CLOCK_EVT_MODE_SHUTDOWN: 154 switch (evt->mode) { 155 case CLOCK_EVT_MODE_ONESHOT: 156 vmi_timer_ops.cancel_alarm(VMI_ONESHOT); 157 break; 158 case CLOCK_EVT_MODE_PERIODIC: 159 vmi_timer_ops.cancel_alarm(VMI_PERIODIC); 160 break; 161 default: 162 break; 163 } 164 break; 165 default: 166 break; 167 } 168} 169 170static int vmi_timer_next_event(unsigned long delta, 171 struct clock_event_device *evt) 172{ 173 /* Unfortunately, set_next_event interface only passes relative 174 * expiry, but we want absolute expiry. It'd be better if were 175 * were passed an aboslute expiry, since a bunch of time may 176 * have been stolen between the time the delta is computed and 177 * when we set the alarm below. */ 178 cycle_t now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_ONESHOT)); 179 180 BUG_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT); 181 vmi_timer_ops.set_alarm(VMI_ONESHOT, now + delta, 0); 182 return 0; 183} 184 185static struct clock_event_device vmi_clockevent = { 186 .name = "vmi-timer", 187 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 188 .shift = 22, 189 .set_mode = vmi_timer_set_mode, 190 .set_next_event = vmi_timer_next_event, 191 .rating = 1000, 192 .irq = 0, 193}; 194 195static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id) 196{ 197 struct clock_event_device *evt = &__get_cpu_var(local_events); 198 evt->event_handler(evt); 199 return IRQ_HANDLED; 200} 201 202static struct irqaction vmi_clock_action = { 203 .name = "vmi-timer", 204 .handler = vmi_timer_interrupt, 205 .flags = IRQF_DISABLED | IRQF_NOBALANCING, 206 .mask = CPU_MASK_ALL, 207}; 208 209static void __devinit vmi_time_init_clockevent(void) 210{ 211 cycle_t cycles_per_msec; 212 struct clock_event_device *evt; 213 214 int cpu = smp_processor_id(); 215 evt = &__get_cpu_var(local_events); 216 217 /* Use cycles_per_msec since div_sc params are 32-bits. */ 218 cycles_per_msec = vmi_timer_ops.get_cycle_frequency(); 219 (void)do_div(cycles_per_msec, 1000); 220 221 memcpy(evt, &vmi_clockevent, sizeof(*evt)); 222 /* Must pick .shift such that .mult fits in 32-bits. Choosing 223 * .shift to be 22 allows 2^(32-22) cycles per nano-seconds 224 * before overflow. */ 225 evt->mult = div_sc(cycles_per_msec, NSEC_PER_MSEC, evt->shift); 226 /* Upper bound is clockevent's use of ulong for cycle deltas. */ 227 evt->max_delta_ns = clockevent_delta2ns(ULONG_MAX, evt); 228 evt->min_delta_ns = clockevent_delta2ns(1, evt); 229 evt->cpumask = cpumask_of_cpu(cpu); 230 231 printk(KERN_WARNING "vmi: registering clock event %s. mult=%lu shift=%u\n", 232 evt->name, evt->mult, evt->shift); 233 clockevents_register_device(evt); 234} 235 236void __init vmi_time_init(void) 237{ 238 /* Disable PIT: BIOSes start PIT CH0 with 18.2hz peridic. */ 239 outb_p(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */ 240 241 vmi_time_init_clockevent(); 242 setup_irq(0, &vmi_clock_action); 243} 244 245#ifdef CONFIG_X86_LOCAL_APIC 246void __devinit vmi_time_bsp_init(void) 247{ 248 /* 249 * On APIC systems, we want local timers to fire on each cpu. We do 250 * this by programming LVTT to deliver timer events to the IRQ handler 251 * for IRQ-0, since we can't re-use the APIC local timer handler 252 * without interfering with that code. 253 */ 254 clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL); 255 local_irq_disable(); 256#ifdef CONFIG_X86_SMP 257 set_irq_chip_and_handler_name(0, &vmi_chip, handle_percpu_irq, "lvtt"); 258#else 259 set_irq_chip_and_handler_name(0, &vmi_chip, handle_edge_irq, "lvtt"); 260#endif 261 vmi_wiring = VMI_ALARM_WIRED_LVTT; 262 apic_write(APIC_LVTT, vmi_get_timer_vector()); 263 local_irq_enable(); 264 clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL); 265} 266 267void __devinit vmi_time_ap_init(void) 268{ 269 vmi_time_init_clockevent(); 270 apic_write(APIC_LVTT, vmi_get_timer_vector()); 271} 272#endif 273 274/** vmi clocksource */ 275 276static cycle_t read_real_cycles(void) 277{ 278 return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL); 279} 280 281static struct clocksource clocksource_vmi = { 282 .name = "vmi-timer", 283 .rating = 450, 284 .read = read_real_cycles, 285 .mask = CLOCKSOURCE_MASK(64), 286 .mult = 0, /* to be set */ 287 .shift = 22, 288 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 289}; 290 291static int __init init_vmi_clocksource(void) 292{ 293 cycle_t cycles_per_msec; 294 295 if (!vmi_timer_ops.get_cycle_frequency) 296 return 0; 297 /* Use khz2mult rather than hz2mult since hz arg is only 32-bits. */ 298 cycles_per_msec = vmi_timer_ops.get_cycle_frequency(); 299 (void)do_div(cycles_per_msec, 1000); 300 301 /* Note that clocksource.{mult, shift} converts in the opposite direction 302 * as clockevents. */ 303 clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec, 304 clocksource_vmi.shift); 305 306 printk(KERN_WARNING "vmi: registering clock source khz=%lld\n", cycles_per_msec); 307 return clocksource_register(&clocksource_vmi); 308 309} 310module_init(init_vmi_clocksource); 311