[PATCH 4/5][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). Signed-off-by: John Stultz <[EMAIL PROTECTED]> arch/x86_64/Kconfig|4 arch/x86_64/kernel/apic.c |2 arch/x86_64/kernel/hpet.c | 65 arch/x86_64/kernel/pmtimer.c | 58 --- arch/x86_64/kernel/smpboot.c |1 arch/x86_64/kernel/time.c | 301 - arch/x86_64/kernel/tsc.c | 108 -- drivers/char/hangcheck-timer.c |2 include/asm-x86_64/proto.h |2 include/asm-x86_64/timex.h |5 10 files changed, 137 insertions(+), 411 deletions(-) linux-2.6.20-rc1_timeofday-arch-x86-64-generic-time-conversion_C7.patch diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index d427553..e1d044c 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -24,6 +24,10 @@ config X86 bool default y +config GENERIC_TIME + bool + default y + config ZONE_DMA32 bool default y diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 7ce7797..723417d 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -786,7 +786,7 @@ static void setup_APIC_timer(unsigned in /* 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)) { diff --git a/arch/x86_64/kernel/hpet.c b/arch/x86_64/kernel/hpet.c index ad67c6b..74d95d0 100644 --- a/arch/x86_64/kernel/hpet.c +++ b/arch/x86_64/kernel/hpet.c @@ -21,12 +21,6 @@ unsigned long hpet_tick; /* HPET clocks 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) @@ -435,3 +429,62 @@ static int __init nohpet_setup(char *s) __setup("nohpet", nohpet_setup); +#define HPET_MASK 0x +#define HPET_SHIFT 22 + +/* FSEC = 10^-15 NSEC = 10^-9 */ +#define FSEC_PER_NSEC 100 + +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, + .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/100fsec = nsec/cyc = mult/2^shift +* fsec/cyc * 1ns/100fsec * 2^shift = mult +* fsec/cyc * 2^shift * 1nsec/100fsec = mult +* (fsec/cyc << shift)/100 = 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); diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c index 7554458..ae8f912 100644 --- a/arch/x86_64/kernel/pmtimer.c +++ b/arch/x86_64/kernel/pmtimer.c @@ -24,15 +24,6 @@ #include #include #include -/* 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 0xFF /* 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
[PATCH 4/5][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). Signed-off-by: John Stultz <[EMAIL PROTECTED]> arch/x86_64/Kconfig |4 arch/x86_64/kernel/apic.c|2 arch/x86_64/kernel/hpet.c| 65 - arch/x86_64/kernel/pmtimer.c | 58 arch/x86_64/kernel/smpboot.c |1 arch/x86_64/kernel/time.c| 301 --- arch/x86_64/kernel/tsc.c | 105 +-- include/asm-x86_64/proto.h |1 include/asm-x86_64/timex.h |5 9 files changed, 133 insertions(+), 409 deletions(-) linux-2.6.19-rc6git11_timeofday-arch-x86-64-generic-time-conversion_C7.patch diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 010d226..20bcd6d 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -24,6 +24,10 @@ config X86 bool default y +config GENERIC_TIME + bool + default y + config ZONE_DMA32 bool default y diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 02f5961..588ef3d 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -696,7 +696,7 @@ static void setup_APIC_timer(unsigned in /* 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)) { diff --git a/arch/x86_64/kernel/hpet.c b/arch/x86_64/kernel/hpet.c index a219786..c00b01a 100644 --- a/arch/x86_64/kernel/hpet.c +++ b/arch/x86_64/kernel/hpet.c @@ -19,12 +19,6 @@ unsigned long hpet_tick; /* HPET clocks 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) @@ -433,3 +427,62 @@ static int __init nohpet_setup(char *s) __setup("nohpet", nohpet_setup); +#define HPET_MASK 0x +#define HPET_SHIFT 22 + +/* FSEC = 10^-15 NSEC = 10^-9 */ +#define FSEC_PER_NSEC 100 + +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, + .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/100fsec = nsec/cyc = mult/2^shift +* fsec/cyc * 1ns/100fsec * 2^shift = mult +* fsec/cyc * 2^shift * 1nsec/100fsec = mult +* (fsec/cyc << shift)/100 = 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); diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c index 7554458..ae8f912 100644 --- a/arch/x86_64/kernel/pmtimer.c +++ b/arch/x86_64/kernel/pmtimer.c @@ -24,15 +24,6 @@ #include #include #include -/* 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 0xFF /* 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_ru