]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/i386/kernel/hpet.c
rtc: rtc-sh: Support 4-digit year on SH7705/SH7710/SH7712.
[linux-2.6-omap-h63xx.git] / arch / i386 / kernel / hpet.c
index f3ab61ee749826282b8d1ee905f631c7b1efb06c..533d4932bc79384805da8d6acee0bd84094e941e 100644 (file)
@@ -3,6 +3,9 @@
 #include <linux/errno.h>
 #include <linux/hpet.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
 
 #include <asm/hpet.h>
 #include <asm/io.h>
@@ -185,6 +188,10 @@ static void hpet_set_mode(enum clock_event_mode mode,
                cfg &= ~HPET_TN_ENABLE;
                hpet_writel(cfg, HPET_T0_CFG);
                break;
+
+       case CLOCK_EVT_MODE_RESUME:
+               hpet_enable_int();
+               break;
        }
 }
 
@@ -197,7 +204,7 @@ static int hpet_next_event(unsigned long delta,
        cnt += delta;
        hpet_writel(cnt, HPET_T0_CMP);
 
-       return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0);
+       return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0;
 }
 
 /*
@@ -215,6 +222,7 @@ static struct clocksource clocksource_hpet = {
        .mask           = HPET_MASK,
        .shift          = HPET_SHIFT,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .resume         = hpet_start_counter,
 };
 
 /*
@@ -224,7 +232,8 @@ int __init hpet_enable(void)
 {
        unsigned long id;
        uint64_t hpet_freq;
-       u64 tmp;
+       u64 tmp, start, now;
+       cycle_t t1;
 
        if (!is_hpet_capable())
                return 0;
@@ -271,6 +280,27 @@ int __init hpet_enable(void)
        /* Start the counter */
        hpet_start_counter();
 
+       /* Verify whether hpet counter works */
+       t1 = read_hpet();
+       rdtscll(start);
+
+       /*
+        * We don't know the TSC frequency yet, but waiting for
+        * 200000 TSC cycles is safe:
+        * 4 GHz == 50us
+        * 1 GHz == 200us
+        */
+       do {
+               rep_nop();
+               rdtscll(now);
+       } while ((now - start) < 200000UL);
+
+       if (t1 == read_hpet()) {
+               printk(KERN_WARNING
+                      "HPET counter not counting. HPET disabled\n");
+               goto out_nohpet;
+       }
+
        /* Initialize and register HPET clocksource
         *
         * hpet period is in femto seconds per cycle
@@ -289,7 +319,6 @@ int __init hpet_enable(void)
 
        clocksource_register(&clocksource_hpet);
 
-
        if (id & HPET_ID_LEGSUP) {
                hpet_enable_int();
                hpet_reserve_platform_timers(id);
@@ -297,7 +326,7 @@ int __init hpet_enable(void)
                 * Start hpet with the boot cpu mask and make it
                 * global after the IO_APIC has been initialized.
                 */
-               hpet_clockevent.cpumask =cpumask_of_cpu(0);
+               hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
                clockevents_register_device(&hpet_clockevent);
                global_clock_event = &hpet_clockevent;
                return 1;
@@ -307,6 +336,7 @@ int __init hpet_enable(void)
 out_nohpet:
        iounmap(hpet_virt_address);
        hpet_virt_address = NULL;
+       boot_hpet_disable = 1;
        return 0;
 }