X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=blobdiff_plain;f=arch%2Fi386%2Fkernel%2Ftime_hpet.c;h=10a0cbb88e754e81cb01604bca90e989c5b9d50c;hp=86b79c6647a3c0ca8e733fc39bb8e82a9fc5a64b;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hpb=e3f6fb6212a7102bdb56ba38fa1e98fe72950475 diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c index 86b79c664..10a0cbb88 100644 --- a/arch/i386/kernel/time_hpet.c +++ b/arch/i386/kernel/time_hpet.c @@ -23,9 +23,10 @@ #include #include -unsigned long hpet_period; /* fsecs / HPET clock */ -unsigned long hpet_tick; /* hpet clks count per tick */ -unsigned long hpet_address; /* hpet memory map physical address */ +static unsigned long hpet_period; /* fsecs / HPET clock */ +unsigned long hpet_tick; /* hpet clks count per tick */ +unsigned long hpet_address; /* hpet memory map physical address */ +int hpet_use_timer; static int use_hpet; /* can be used for runtime check of hpet */ static int boot_hpet_disable; /* boottime override for HPET timer */ @@ -38,7 +39,7 @@ int hpet_readl(unsigned long a) return readl(hpet_virt_address + a); } -void hpet_writel(unsigned long d, unsigned long a) +static void hpet_writel(unsigned long d, unsigned long a) { writel(d, hpet_virt_address + a); } @@ -49,7 +50,7 @@ void hpet_writel(unsigned long d, unsigned long a) * comparator value and continue. Next tick can be caught by checking * for a change in the comparator value. Used in apic.c. */ -void __init wait_hpet_tick(void) +static void __init wait_hpet_tick(void) { unsigned int start_cmp_val, end_cmp_val; @@ -73,26 +74,30 @@ static int hpet_timer_stop_set_go(unsigned long tick) hpet_writel(0, HPET_COUNTER); hpet_writel(0, HPET_COUNTER + 4); - /* - * Set up timer 0, as periodic with first interrupt to happen at - * hpet_tick, and period also hpet_tick. - */ - cfg = hpet_readl(HPET_T0_CFG); - cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | - HPET_TN_SETVAL | HPET_TN_32BIT; - hpet_writel(cfg, HPET_T0_CFG); - /* - * Some systems seems to need two writes to HPET_T0_CMP, - * to get interrupts working - */ - hpet_writel(tick, HPET_T0_CMP); - hpet_writel(tick, HPET_T0_CMP); + if (hpet_use_timer) { + /* + * Set up timer 0, as periodic with first interrupt to happen at + * hpet_tick, and period also hpet_tick. + */ + cfg = hpet_readl(HPET_T0_CFG); + cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | + HPET_TN_SETVAL | HPET_TN_32BIT; + hpet_writel(cfg, HPET_T0_CFG); + /* + * The first write after writing TN_SETVAL to the config register sets + * the counter value, the second write sets the threshold. + */ + hpet_writel(tick, HPET_T0_CMP); + hpet_writel(tick, HPET_T0_CMP); + } /* * Go! */ cfg = hpet_readl(HPET_CFG); - cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY; + if (hpet_use_timer) + cfg |= HPET_CFG_LEGACY; + cfg |= HPET_CFG_ENABLE; hpet_writel(cfg, HPET_CFG); return 0; @@ -121,13 +126,17 @@ int __init hpet_enable(void) id = hpet_readl(HPET_ID); /* - * We are checking for value '1' or more in number field. - * So, we are OK with HPET_EMULATE_RTC part too, where we need - * to have atleast 2 timers. + * We are checking for value '1' or more in number field if + * CONFIG_HPET_EMULATE_RTC is set because we will need an + * additional timer for RTC emulation. + * However, we can do with one timer otherwise using the + * the single HPET timer for system time. */ - if (!(id & HPET_ID_NUMBER) || - !(id & HPET_ID_LEGSUP)) +#ifdef CONFIG_HPET_EMULATE_RTC + if (!(id & HPET_ID_NUMBER)) return -1; +#endif + hpet_period = hpet_readl(HPET_PERIOD); if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) @@ -146,6 +155,8 @@ int __init hpet_enable(void) if (hpet_tick_rem > (hpet_period >> 1)) hpet_tick++; /* rounding the result */ + hpet_use_timer = id & HPET_ID_LEGSUP; + if (hpet_timer_stop_set_go(hpet_tick)) return -1; @@ -196,7 +207,8 @@ int __init hpet_enable(void) #endif #ifdef CONFIG_X86_LOCAL_APIC - wait_timer_tick = wait_hpet_tick; + if (hpet_use_timer) + wait_timer_tick = wait_hpet_tick; #endif return 0; }