aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/time.c2
-rw-r--r--arch/i386/kernel/time_hpet.c48
-rw-r--r--arch/i386/kernel/timers/timer_hpet.c11
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c2
-rw-r--r--include/asm-i386/hpet.h1
5 files changed, 37 insertions, 27 deletions
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 4d75b373f90e..a0dcb7c87c30 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -441,7 +441,7 @@ static void __init hpet_time_init(void)
441 set_normalized_timespec(&wall_to_monotonic, 441 set_normalized_timespec(&wall_to_monotonic,
442 -xtime.tv_sec, -xtime.tv_nsec); 442 -xtime.tv_sec, -xtime.tv_nsec);
443 443
444 if (hpet_enable() >= 0) { 444 if ((hpet_enable() >= 0) && hpet_use_timer) {
445 printk("Using HPET for base-timer\n"); 445 printk("Using HPET for base-timer\n");
446 } 446 }
447 447
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 244a31b04be7..10a0cbb88e75 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -26,6 +26,7 @@
26static unsigned long hpet_period; /* fsecs / HPET clock */ 26static unsigned long hpet_period; /* fsecs / HPET clock */
27unsigned long hpet_tick; /* hpet clks count per tick */ 27unsigned long hpet_tick; /* hpet clks count per tick */
28unsigned long hpet_address; /* hpet memory map physical address */ 28unsigned long hpet_address; /* hpet memory map physical address */
29int hpet_use_timer;
29 30
30static int use_hpet; /* can be used for runtime check of hpet */ 31static int use_hpet; /* can be used for runtime check of hpet */
31static int boot_hpet_disable; /* boottime override for HPET timer */ 32static int boot_hpet_disable; /* boottime override for HPET timer */
@@ -73,27 +74,30 @@ static int hpet_timer_stop_set_go(unsigned long tick)
73 hpet_writel(0, HPET_COUNTER); 74 hpet_writel(0, HPET_COUNTER);
74 hpet_writel(0, HPET_COUNTER + 4); 75 hpet_writel(0, HPET_COUNTER + 4);
75 76
76 /* 77 if (hpet_use_timer) {
77 * Set up timer 0, as periodic with first interrupt to happen at 78 /*
78 * hpet_tick, and period also hpet_tick. 79 * Set up timer 0, as periodic with first interrupt to happen at
79 */ 80 * hpet_tick, and period also hpet_tick.
80 cfg = hpet_readl(HPET_T0_CFG); 81 */
81 cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | 82 cfg = hpet_readl(HPET_T0_CFG);
82 HPET_TN_SETVAL | HPET_TN_32BIT; 83 cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
83 hpet_writel(cfg, HPET_T0_CFG); 84 HPET_TN_SETVAL | HPET_TN_32BIT;
84 85 hpet_writel(cfg, HPET_T0_CFG);
85 /*
86 * The first write after writing TN_SETVAL to the config register sets
87 * the counter value, the second write sets the threshold.
88 */
89 hpet_writel(tick, HPET_T0_CMP);
90 hpet_writel(tick, HPET_T0_CMP);
91 86
87 /*
88 * The first write after writing TN_SETVAL to the config register sets
89 * the counter value, the second write sets the threshold.
90 */
91 hpet_writel(tick, HPET_T0_CMP);
92 hpet_writel(tick, HPET_T0_CMP);
93 }
92 /* 94 /*
93 * Go! 95 * Go!
94 */ 96 */
95 cfg = hpet_readl(HPET_CFG); 97 cfg = hpet_readl(HPET_CFG);
96 cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY; 98 if (hpet_use_timer)
99 cfg |= HPET_CFG_LEGACY;
100 cfg |= HPET_CFG_ENABLE;
97 hpet_writel(cfg, HPET_CFG); 101 hpet_writel(cfg, HPET_CFG);
98 102
99 return 0; 103 return 0;
@@ -128,12 +132,11 @@ int __init hpet_enable(void)
128 * However, we can do with one timer otherwise using the 132 * However, we can do with one timer otherwise using the
129 * the single HPET timer for system time. 133 * the single HPET timer for system time.
130 */ 134 */
131 if (
132#ifdef CONFIG_HPET_EMULATE_RTC 135#ifdef CONFIG_HPET_EMULATE_RTC
133 !(id & HPET_ID_NUMBER) || 136 if (!(id & HPET_ID_NUMBER))
134#endif
135 !(id & HPET_ID_LEGSUP))
136 return -1; 137 return -1;
138#endif
139
137 140
138 hpet_period = hpet_readl(HPET_PERIOD); 141 hpet_period = hpet_readl(HPET_PERIOD);
139 if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) 142 if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD))
@@ -152,6 +155,8 @@ int __init hpet_enable(void)
152 if (hpet_tick_rem > (hpet_period >> 1)) 155 if (hpet_tick_rem > (hpet_period >> 1))
153 hpet_tick++; /* rounding the result */ 156 hpet_tick++; /* rounding the result */
154 157
158 hpet_use_timer = id & HPET_ID_LEGSUP;
159
155 if (hpet_timer_stop_set_go(hpet_tick)) 160 if (hpet_timer_stop_set_go(hpet_tick))
156 return -1; 161 return -1;
157 162
@@ -202,7 +207,8 @@ int __init hpet_enable(void)
202#endif 207#endif
203 208
204#ifdef CONFIG_X86_LOCAL_APIC 209#ifdef CONFIG_X86_LOCAL_APIC
205 wait_timer_tick = wait_hpet_tick; 210 if (hpet_use_timer)
211 wait_timer_tick = wait_hpet_tick;
206#endif 212#endif
207 return 0; 213 return 0;
208} 214}
diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
index 713134e71844..f778f471a09a 100644
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ b/arch/i386/kernel/timers/timer_hpet.c
@@ -79,7 +79,7 @@ static unsigned long get_offset_hpet(void)
79 79
80 eax = hpet_readl(HPET_COUNTER); 80 eax = hpet_readl(HPET_COUNTER);
81 eax -= hpet_last; /* hpet delta */ 81 eax -= hpet_last; /* hpet delta */
82 82 eax = min(hpet_tick, eax);
83 /* 83 /*
84 * Time offset = (hpet delta) * ( usecs per HPET clock ) 84 * Time offset = (hpet delta) * ( usecs per HPET clock )
85 * = (hpet delta) * ( usecs per tick / HPET clocks per tick) 85 * = (hpet delta) * ( usecs per tick / HPET clocks per tick)
@@ -105,9 +105,12 @@ static void mark_offset_hpet(void)
105 last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; 105 last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
106 rdtsc(last_tsc_low, last_tsc_high); 106 rdtsc(last_tsc_low, last_tsc_high);
107 107
108 offset = hpet_readl(HPET_T0_CMP) - hpet_tick; 108 if (hpet_use_timer)
109 if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { 109 offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
110 int lost_ticks = (offset - hpet_last) / hpet_tick; 110 else
111 offset = hpet_readl(HPET_COUNTER);
112 if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 0))) {
113 int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1;
111 jiffies_64 += lost_ticks; 114 jiffies_64 += lost_ticks;
112 } 115 }
113 hpet_last = offset; 116 hpet_last = offset;
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index a685994e5c8e..7926d967be00 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -477,7 +477,7 @@ static int __init init_tsc(char* override)
477 if (cpu_has_tsc) { 477 if (cpu_has_tsc) {
478 unsigned long tsc_quotient; 478 unsigned long tsc_quotient;
479#ifdef CONFIG_HPET_TIMER 479#ifdef CONFIG_HPET_TIMER
480 if (is_hpet_enabled()){ 480 if (is_hpet_enabled() && hpet_use_timer) {
481 unsigned long result, remain; 481 unsigned long result, remain;
482 printk("Using TSC for gettimeofday\n"); 482 printk("Using TSC for gettimeofday\n");
483 tsc_quotient = calibrate_tsc_hpet(NULL); 483 tsc_quotient = calibrate_tsc_hpet(NULL);
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index 6e20b079f1d3..16ef9f996e3f 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -92,6 +92,7 @@
92 92
93extern unsigned long hpet_tick; /* hpet clks count per tick */ 93extern unsigned long hpet_tick; /* hpet clks count per tick */
94extern unsigned long hpet_address; /* hpet memory map physical address */ 94extern unsigned long hpet_address; /* hpet memory map physical address */
95extern int hpet_use_timer;
95 96
96extern int hpet_rtc_timer_init(void); 97extern int hpet_rtc_timer_init(void);
97extern int hpet_enable(void); 98extern int hpet_enable(void);