Skip to content

Commit

Permalink
x86_64: Add (not yet used) clock event functions
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
  • Loading branch information
Thomas Gleixner authored and Thomas Gleixner committed Oct 12, 2007
1 parent 0229068 commit ba7eda4
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
79 changes: 79 additions & 0 deletions arch/x86/kernel/apic_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/sysdev.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/clockchips.h>

#include <asm/atomic.h>
#include <asm/smp.h>
Expand Down Expand Up @@ -57,6 +58,77 @@ static struct resource lapic_resource = {

static unsigned int calibration_result;

static int lapic_next_event(unsigned long delta,
struct clock_event_device *evt);
static void lapic_timer_setup(enum clock_event_mode mode,
struct clock_event_device *evt);

static void lapic_timer_broadcast(cpumask_t mask);

static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen);

static struct clock_event_device lapic_clockevent = {
.name = "lapic",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
| CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
.shift = 32,
.set_mode = lapic_timer_setup,
.set_next_event = lapic_next_event,
.broadcast = lapic_timer_broadcast,
.rating = 100,
.irq = -1,
};
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);

static int lapic_next_event(unsigned long delta,
struct clock_event_device *evt)
{
apic_write(APIC_TMICT, delta);
return 0;
}

static void lapic_timer_setup(enum clock_event_mode mode,
struct clock_event_device *evt)
{
unsigned long flags;
unsigned int v;

/* Lapic used as dummy for broadcast ? */
if (evt->features & CLOCK_EVT_FEAT_DUMMY)
return;

local_irq_save(flags);

switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
case CLOCK_EVT_MODE_ONESHOT:
__setup_APIC_LVTT(calibration_result,
mode != CLOCK_EVT_MODE_PERIODIC, 1);
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
v = apic_read(APIC_LVTT);
v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
apic_write(APIC_LVTT, v);
break;
case CLOCK_EVT_MODE_RESUME:
/* Nothing to do here */
break;
}

local_irq_restore(flags);
}

/*
* Local APIC timer broadcast function
*/
static void lapic_timer_broadcast(cpumask_t mask)
{
#ifdef CONFIG_SMP
send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
#endif
}

/*
* cpu_mask that denotes the CPUs that needs timer interrupt coming in as
* IPIs in place of local APIC timers
Expand Down Expand Up @@ -866,6 +938,13 @@ static void __init calibrate_APIC_clock(void)
printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
result / 1000 / 1000, result / 1000 % 1000);

/* Calculate the scaled math multiplication factor */
lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32);
lapic_clockevent.max_delta_ns =
clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
lapic_clockevent.min_delta_ns =
clockevent_delta2ns(0xF, &lapic_clockevent);

calibration_result = result / HZ;
}

Expand Down
6 changes: 6 additions & 0 deletions arch/x86_64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ config CLOCKSOURCE_WATCHDOG
bool
default y

config GENERIC_CLOCKEVENTS_MIGR
bool
default y

config ZONE_DMA32
bool
default y
Expand Down Expand Up @@ -134,6 +138,8 @@ source "init/Kconfig"

menu "Processor type and features"

source "kernel/time/Kconfig"

choice
prompt "Subarchitecture Type"
default X86_PC
Expand Down

0 comments on commit ba7eda4

Please sign in to comment.