aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hpet.c
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2007-07-20 14:22:30 -0400
committerTony Luck <tony.luck@intel.com>2007-07-20 14:22:30 -0400
commit0aa366f351d044703e25c8425e508170e80d83b1 (patch)
tree485040cbef6157b9bcb2e7b1b85920d1e391ab68 /drivers/char/hpet.c
parent5bae7ac9feba925fd0099057f6b23d7be80b7b41 (diff)
[IA64] Convert to generic timekeeping/clocksource
This is a merge of Peter Keilty's initial patch (which was revived by Bob Picco) for this with Hidetoshi Seto's fixes and scaling improvements. Acked-by: Bob Picco <bob.picco@hp.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'drivers/char/hpet.c')
-rw-r--r--drivers/char/hpet.c70
1 files changed, 39 insertions, 31 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 0be700f4e8fd..ba0e74ad74bb 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -29,6 +29,7 @@
29#include <linux/bcd.h> 29#include <linux/bcd.h>
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <linux/bitops.h> 31#include <linux/bitops.h>
32#include <linux/clocksource.h>
32 33
33#include <asm/current.h> 34#include <asm/current.h>
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
@@ -51,8 +52,34 @@
51 52
52#define HPET_RANGE_SIZE 1024 /* from HPET spec */ 53#define HPET_RANGE_SIZE 1024 /* from HPET spec */
53 54
55#if BITS_PER_LONG == 64
56#define write_counter(V, MC) writeq(V, MC)
57#define read_counter(MC) readq(MC)
58#else
59#define write_counter(V, MC) writel(V, MC)
60#define read_counter(MC) readl(MC)
61#endif
62
54static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; 63static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
55 64
65static void __iomem *hpet_mctr;
66
67static cycle_t read_hpet(void)
68{
69 return (cycle_t)read_counter((void __iomem *)hpet_mctr);
70}
71
72static struct clocksource clocksource_hpet = {
73 .name = "hpet",
74 .rating = 250,
75 .read = read_hpet,
76 .mask = 0xffffffffffffffff,
77 .mult = 0, /*to be caluclated*/
78 .shift = 10,
79 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
80};
81static struct clocksource *hpet_clocksource;
82
56/* A lock for concurrent access by app and isr hpet activity. */ 83/* A lock for concurrent access by app and isr hpet activity. */
57static DEFINE_SPINLOCK(hpet_lock); 84static DEFINE_SPINLOCK(hpet_lock);
58/* A lock for concurrent intermodule access to hpet and isr hpet activity. */ 85/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
@@ -79,7 +106,7 @@ struct hpets {
79 struct hpets *hp_next; 106 struct hpets *hp_next;
80 struct hpet __iomem *hp_hpet; 107 struct hpet __iomem *hp_hpet;
81 unsigned long hp_hpet_phys; 108 unsigned long hp_hpet_phys;
82 struct time_interpolator *hp_interpolator; 109 struct clocksource *hp_clocksource;
83 unsigned long long hp_tick_freq; 110 unsigned long long hp_tick_freq;
84 unsigned long hp_delta; 111 unsigned long hp_delta;
85 unsigned int hp_ntimer; 112 unsigned int hp_ntimer;
@@ -94,13 +121,6 @@ static struct hpets *hpets;
94#define HPET_PERIODIC 0x0004 121#define HPET_PERIODIC 0x0004
95#define HPET_SHARED_IRQ 0x0008 122#define HPET_SHARED_IRQ 0x0008
96 123
97#if BITS_PER_LONG == 64
98#define write_counter(V, MC) writeq(V, MC)
99#define read_counter(MC) readq(MC)
100#else
101#define write_counter(V, MC) writel(V, MC)
102#define read_counter(MC) readl(MC)
103#endif
104 124
105#ifndef readq 125#ifndef readq
106static inline unsigned long long readq(void __iomem *addr) 126static inline unsigned long long readq(void __iomem *addr)
@@ -737,27 +757,6 @@ static ctl_table dev_root[] = {
737 757
738static struct ctl_table_header *sysctl_header; 758static struct ctl_table_header *sysctl_header;
739 759
740static void hpet_register_interpolator(struct hpets *hpetp)
741{
742#ifdef CONFIG_TIME_INTERPOLATION
743 struct time_interpolator *ti;
744
745 ti = kzalloc(sizeof(*ti), GFP_KERNEL);
746 if (!ti)
747 return;
748
749 ti->source = TIME_SOURCE_MMIO64;
750 ti->shift = 10;
751 ti->addr = &hpetp->hp_hpet->hpet_mc;
752 ti->frequency = hpetp->hp_tick_freq;
753 ti->drift = HPET_DRIFT;
754 ti->mask = -1;
755
756 hpetp->hp_interpolator = ti;
757 register_time_interpolator(ti);
758#endif
759}
760
761/* 760/*
762 * Adjustment for when arming the timer with 761 * Adjustment for when arming the timer with
763 * initial conditions. That is, main counter 762 * initial conditions. That is, main counter
@@ -909,7 +908,16 @@ int hpet_alloc(struct hpet_data *hdp)
909 } 908 }
910 909
911 hpetp->hp_delta = hpet_calibrate(hpetp); 910 hpetp->hp_delta = hpet_calibrate(hpetp);
912 hpet_register_interpolator(hpetp); 911
912 if (!hpet_clocksource) {
913 hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
914 CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
915 clocksource_hpet.mult = clocksource_hz2mult(hpetp->hp_tick_freq,
916 clocksource_hpet.shift);
917 clocksource_register(&clocksource_hpet);
918 hpetp->hp_clocksource = &clocksource_hpet;
919 hpet_clocksource = &clocksource_hpet;
920 }
913 921
914 return 0; 922 return 0;
915} 923}
@@ -995,7 +1003,7 @@ static int hpet_acpi_add(struct acpi_device *device)
995 1003
996static int hpet_acpi_remove(struct acpi_device *device, int type) 1004static int hpet_acpi_remove(struct acpi_device *device, int type)
997{ 1005{
998 /* XXX need to unregister interpolator, dealloc mem, etc */ 1006 /* XXX need to unregister clocksource, dealloc mem, etc */
999 return -EINVAL; 1007 return -EINVAL;
1000} 1008}
1001 1009