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

Commit 5d0cf410 authored by John Stultz's avatar John Stultz Committed by Linus Torvalds
Browse files

[PATCH] Time: i386 Clocksource Drivers



Implement the time sources for i386 (acpi_pm, cyclone, hpet, pit, and tsc).
With this patch, the conversion of the i386 arch to the generic timekeeping
code should be complete.

The patch should be fairly straight forward, only adding the new clocksources.

[hirofumi@mail.parknet.co.jp: acpi_pm cleanup]
Signed-off-by: default avatarJohn Stultz <johnstul@us.ibm.com>
Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarJohn Stultz <johnstul@us.ibm.com>
Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 61743fe4
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -180,6 +180,11 @@ running once the system is up.
			override platform specific driver.
			See also Documentation/acpi-hotkey.txt.

	acpi_pm_good	[IA-32,X86-64]
			Override the pmtimer bug detection: force the kernel
			to assume that this machine's pmtimer latches its value
			and always returns good values.

	enable_timer_pin_1 [i386,x86-64]
			Enable PIN 1 of APIC timer
			Can be useful to work around chipset bugs
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ obj-$(CONFIG_EFI) += efi.o efi_stub.o
obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault.o
obj-$(CONFIG_VM86)		+= vm86.o
obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
obj-$(CONFIG_HPET_TIMER) 	+= hpet.o

EXTRA_AFLAGS   := -traditional

+67 −0
Original line number Diff line number Diff line
#include <linux/clocksource.h>
#include <linux/errno.h>
#include <linux/hpet.h>
#include <linux/init.h>

#include <asm/hpet.h>
#include <asm/io.h>

#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);
}

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

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 =
		(void __iomem*)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 register_clocksource(&clocksource_hpet);
}

module_init(init_hpet_clocksource);
+53 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
 * i8253.c  8253/PIT functions
 *
 */
#include <linux/clocksource.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <linux/sysdev.h>
@@ -30,3 +31,55 @@ void setup_pit_timer(void)
	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
	spin_unlock_irqrestore(&i8253_lock, flags);
}

/*
 * Since the PIT overflows every tick, its not very useful
 * to just read by itself. So use jiffies to emulate a free
 * running counter:
 */
static cycle_t pit_read(void)
{
	unsigned long flags;
	int count;
	u64 jifs;

	spin_lock_irqsave(&i8253_lock, flags);
	outb_p(0x00, PIT_MODE);	/* latch the count ASAP */
	count = inb_p(PIT_CH0);	/* read the latched count */
	count |= inb_p(PIT_CH0) << 8;

	/* VIA686a test code... reset the latch if count > max + 1 */
	if (count > LATCH) {
		outb_p(0x34, PIT_MODE);
		outb_p(LATCH & 0xff, PIT_CH0);
		outb(LATCH >> 8, PIT_CH0);
		count = LATCH - 1;
	}
	spin_unlock_irqrestore(&i8253_lock, flags);

	jifs = jiffies_64;

	jifs -= INITIAL_JIFFIES;
	count = (LATCH-1) - count;

	return (cycle_t)(jifs * LATCH) + count;
}

static struct clocksource clocksource_pit = {
	.name	= "pit",
	.rating = 110,
	.read	= pit_read,
	.mask	= (cycle_t)-1,
	.mult	= 0,
	.shift	= 20,
};

static int __init init_pit_clocksource(void)
{
	if (num_possible_cpus() > 4) /* PIT does not scale! */
		return 0;

	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
	return register_clocksource(&clocksource_pit);
}
module_init(init_pit_clocksource);
+0 −3
Original line number Diff line number Diff line
@@ -82,9 +82,6 @@ extern unsigned long wall_jiffies;
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);

/* XXX - necessary to keep things compiling. to be removed later */
u32 pmtmr_ioport;

/*
 * This is a special lock that is owned by the CPU and holds the index
 * register we are working with.  It is required for NMI access to the
Loading