Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1489939f authored by John Stultz's avatar John Stultz Committed by Linus Torvalds
Browse files

[PATCH] time: x86_64: convert x86_64 to use GENERIC_TIME



This patch converts x86_64 to use the GENERIC_TIME infrastructure and adds
clocksource structures for both TSC and HPET (ACPI PM is shared w/ i386).

[akpm@osdl.org: fix printk timestamps]
[akpm@osdl.org: fix printk ckeanups]
[akpm@osdl.org: hpet build fix]
Signed-off-by: default avatarJohn Stultz <johnstul@us.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andi Kleen <ak@muc.de>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c37e7bb5
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -24,6 +24,10 @@ config X86
	bool
	default y

config GENERIC_TIME
	bool
	default y

config ZONE_DMA32
	bool
	default y
+1 −1
Original line number Diff line number Diff line
@@ -786,7 +786,7 @@ static void setup_APIC_timer(unsigned int clocks)
	/* Turn off PIT interrupt if we use APIC timer as main timer.
	   Only works with the PM timer right now
	   TBD fix it for HPET too. */
	if (vxtime.mode == VXTIME_PMTMR &&
	if ((pmtmr_ioport != 0) &&
		smp_processor_id() == boot_cpu_id &&
		apic_runs_main_timer == 1 &&
		!cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) {
+58 −6
Original line number Diff line number Diff line
@@ -21,12 +21,6 @@ unsigned long hpet_tick; /* HPET clocks / interrupt */
int hpet_use_timer;		/* Use counter of hpet for time keeping,
				 * otherwise PIT
				 */
unsigned int do_gettimeoffset_hpet(void)
{
	/* cap counter read to one tick to avoid inconsistencies */
	unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
	return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;
}

#ifdef	CONFIG_HPET
static __init int late_hpet_init(void)
@@ -451,3 +445,61 @@ static int __init nohpet_setup(char *s)

__setup("nohpet", nohpet_setup);

#define HPET_MASK	0xFFFFFFFF
#define HPET_SHIFT	22

/* FSEC = 10^-15 NSEC = 10^-9 */
#define FSEC_PER_NSEC	1000000

static void *hpet_ptr;

static cycle_t read_hpet(void)
{
	return (cycle_t)readl(hpet_ptr);
}

struct clocksource clocksource_hpet = {
	.name		= "hpet",
	.rating		= 250,
	.read		= read_hpet,
	.mask		= (cycle_t)HPET_MASK,
	.mult		= 0, /* set below */
	.shift		= HPET_SHIFT,
	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
};

static int __init init_hpet_clocksource(void)
{
	unsigned long hpet_period;
	void __iomem *hpet_base;
	u64 tmp;

	if (!hpet_address)
		return -ENODEV;

	/* calculate the hpet address: */
	hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
	hpet_ptr = hpet_base + HPET_COUNTER;

	/* calculate the frequency: */
	hpet_period = readl(hpet_base + HPET_PERIOD);

	/*
	 * hpet period is in femto seconds per cycle
	 * so we need to convert this to ns/cyc units
	 * aproximated by mult/2^shift
	 *
	 *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
	 *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
	 *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
	 *  (fsec/cyc << shift)/1000000 = mult
	 *  (hpet_period << shift)/FSEC_PER_NSEC = mult
	 */
	tmp = (u64)hpet_period << HPET_SHIFT;
	do_div(tmp, FSEC_PER_NSEC);
	clocksource_hpet.mult = (u32)tmp;

	return clocksource_register(&clocksource_hpet);
}

module_init(init_hpet_clocksource);
+0 −58
Original line number Diff line number Diff line
@@ -24,15 +24,6 @@
#include <asm/msr.h>
#include <asm/vsyscall.h>

/* The I/O port the PMTMR resides at.
 * The location is detected during setup_arch(),
 * in arch/i386/kernel/acpi/boot.c */
u32 pmtmr_ioport __read_mostly;

/* value of the Power timer at last timer interrupt */
static u32 offset_delay;
static u32 last_pmtmr_tick;

#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */

static inline u32 cyc2us(u32 cycles)
@@ -48,38 +39,6 @@ static inline u32 cyc2us(u32 cycles)
	return (cycles >> 10);
}

int pmtimer_mark_offset(void)
{
	static int first_run = 1;
	unsigned long tsc;
	u32 lost;

	u32 tick = inl(pmtmr_ioport);
	u32 delta;

	delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);

	last_pmtmr_tick = tick;
	monotonic_base += delta * NSEC_PER_USEC;

	delta += offset_delay;

	lost = delta / (USEC_PER_SEC / HZ);
	offset_delay = delta % (USEC_PER_SEC / HZ);

	rdtscll(tsc);
	vxtime.last_tsc = tsc - offset_delay * (u64)cpu_khz / 1000;

	/* don't calculate delay for first run,
	   or if we've got less then a tick */
	if (first_run || (lost < 1)) {
		first_run = 0;
		offset_delay = 0;
	}

	return lost - 1;
}

static unsigned pmtimer_wait_tick(void)
{
	u32 a, b;
@@ -101,23 +60,6 @@ void pmtimer_wait(unsigned us)
	} while (cyc2us(b - a) < us);
}

void pmtimer_resume(void)
{
	last_pmtmr_tick = inl(pmtmr_ioport);
}

unsigned int do_gettimeoffset_pm(void)
{
	u32 now, offset, delta = 0;

	offset = last_pmtmr_tick;
	now = inl(pmtmr_ioport);
	delta = (now - offset) & ACPI_PM_MASK;

	return offset_delay + cyc2us(delta);
}


static int __init nopmtimer_setup(char *s)
{
	pmtmr_ioport = 0;
+0 −1
Original line number Diff line number Diff line
@@ -982,7 +982,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
	smp_cleanup_boot();
	setup_ioapic_dest();
	check_nmi_watchdog();
	time_init_gtod();
}

#ifdef CONFIG_HOTPLUG_CPU
Loading