x86_64: Add (not yet used) clock event functions
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>
This commit is contained in:
committed by
Thomas Gleixner
parent
0229068334
commit
ba7eda4c60
@@ -25,6 +25,7 @@
|
|||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/clockchips.h>
|
||||||
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
@@ -57,6 +58,77 @@ static struct resource lapic_resource = {
|
|||||||
|
|
||||||
static unsigned int calibration_result;
|
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
|
* cpu_mask that denotes the CPUs that needs timer interrupt coming in as
|
||||||
* IPIs in place of local APIC timers
|
* IPIs in place of local APIC timers
|
||||||
@@ -866,6 +938,13 @@ static void __init calibrate_APIC_clock(void)
|
|||||||
printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
|
printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
|
||||||
result / 1000 / 1000, result / 1000 % 1000);
|
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;
|
calibration_result = result / HZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,6 +40,10 @@ config CLOCKSOURCE_WATCHDOG
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config GENERIC_CLOCKEVENTS_MIGR
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config ZONE_DMA32
|
config ZONE_DMA32
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
@@ -134,6 +138,8 @@ source "init/Kconfig"
|
|||||||
|
|
||||||
menu "Processor type and features"
|
menu "Processor type and features"
|
||||||
|
|
||||||
|
source "kernel/time/Kconfig"
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Subarchitecture Type"
|
prompt "Subarchitecture Type"
|
||||||
default X86_PC
|
default X86_PC
|
||||||
|
Reference in New Issue
Block a user