diff options
-rw-r--r-- | arch/i386/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/time_hpet.c | 48 | ||||
-rw-r--r-- | arch/i386/kernel/timers/timer_hpet.c | 11 | ||||
-rw-r--r-- | arch/i386/kernel/timers/timer_tsc.c | 2 | ||||
-rw-r--r-- | include/asm-i386/hpet.h | 1 |
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 @@ | |||
26 | static unsigned long hpet_period; /* fsecs / HPET clock */ | 26 | static unsigned long hpet_period; /* fsecs / HPET clock */ |
27 | unsigned long hpet_tick; /* hpet clks count per tick */ | 27 | unsigned long hpet_tick; /* hpet clks count per tick */ |
28 | unsigned long hpet_address; /* hpet memory map physical address */ | 28 | unsigned long hpet_address; /* hpet memory map physical address */ |
29 | int hpet_use_timer; | ||
29 | 30 | ||
30 | static int use_hpet; /* can be used for runtime check of hpet */ | 31 | static int use_hpet; /* can be used for runtime check of hpet */ |
31 | static int boot_hpet_disable; /* boottime override for HPET timer */ | 32 | static 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 | ||
93 | extern unsigned long hpet_tick; /* hpet clks count per tick */ | 93 | extern unsigned long hpet_tick; /* hpet clks count per tick */ |
94 | extern unsigned long hpet_address; /* hpet memory map physical address */ | 94 | extern unsigned long hpet_address; /* hpet memory map physical address */ |
95 | extern int hpet_use_timer; | ||
95 | 96 | ||
96 | extern int hpet_rtc_timer_init(void); | 97 | extern int hpet_rtc_timer_init(void); |
97 | extern int hpet_enable(void); | 98 | extern int hpet_enable(void); |