vserver 2.0 rc7
[linux-2.6.git] / arch / i386 / kernel / time_hpet.c
index 86b79c6..10a0cbb 100644 (file)
 #include <asm/hpet.h>
 #include <linux/hpet.h>
 
-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;
 }