drm/radeon/kms: clear confusion in GART init/deinit path
[safe/jmp/linux-2.6] / arch / x86 / kernel / hpet.c
index 1d86ca3..dedc2bd 100644 (file)
@@ -231,27 +231,42 @@ static struct clock_event_device hpet_clockevent = {
        .rating         = 50,
 };
 
-static void hpet_start_counter(void)
+static void hpet_stop_counter(void)
 {
        unsigned long cfg = hpet_readl(HPET_CFG);
-
        cfg &= ~HPET_CFG_ENABLE;
        hpet_writel(cfg, HPET_CFG);
+}
+
+static void hpet_reset_counter(void)
+{
        hpet_writel(0, HPET_COUNTER);
        hpet_writel(0, HPET_COUNTER + 4);
+}
+
+static void hpet_start_counter(void)
+{
+       unsigned long cfg = hpet_readl(HPET_CFG);
        cfg |= HPET_CFG_ENABLE;
        hpet_writel(cfg, HPET_CFG);
 }
 
+static void hpet_restart_counter(void)
+{
+       hpet_stop_counter();
+       hpet_reset_counter();
+       hpet_start_counter();
+}
+
 static void hpet_resume_device(void)
 {
        force_hpet_resume();
 }
 
-static void hpet_restart_counter(void)
+static void hpet_resume_counter(void)
 {
        hpet_resume_device();
-       hpet_start_counter();
+       hpet_restart_counter();
 }
 
 static void hpet_enable_legacy_int(void)
@@ -304,6 +319,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
+               hpet_stop_counter();
                delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult;
                delta >>= evt->shift;
                now = hpet_readl(HPET_COUNTER);
@@ -314,14 +330,17 @@ static void hpet_set_mode(enum clock_event_mode mode,
                cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
                       HPET_TN_SETVAL | HPET_TN_32BIT;
                hpet_writel(cfg, HPET_Tn_CFG(timer));
-               /*
-                * The first write after writing TN_SETVAL to the
-                * config register sets the counter value, the second
-                * write sets the period.
-                */
                hpet_writel(cmp, HPET_Tn_CMP(timer));
                udelay(1);
+               /*
+                * HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL
+                * cleared) to T0_CMP to set the period. The HPET_TN_SETVAL
+                * bit is automatically cleared after the first write.
+                * (See AMD-8111 HyperTransport I/O Hub Data Sheet,
+                * Publication # 24674)
+                */
                hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
+               hpet_start_counter();
                hpet_print_config();
                break;
 
@@ -491,7 +510,8 @@ static int hpet_setup_irq(struct hpet_dev *dev)
 {
 
        if (request_irq(dev->irq, hpet_interrupt_handler,
-                       IRQF_DISABLED|IRQF_NOBALANCING, dev->name, dev))
+                       IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+                       dev->name, dev))
                return -1;
 
        disable_irq(dev->irq);
@@ -719,7 +739,7 @@ static int hpet_cpuhp_notify(struct notifier_block *n,
 /*
  * Clock source related code
  */
-static cycle_t read_hpet(void)
+static cycle_t read_hpet(struct clocksource *cs)
 {
        return (cycle_t)hpet_readl(HPET_COUNTER);
 }
@@ -738,7 +758,7 @@ static struct clocksource clocksource_hpet = {
        .mask           = HPET_MASK,
        .shift          = HPET_SHIFT,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-       .resume         = hpet_restart_counter,
+       .resume         = hpet_resume_counter,
 #ifdef CONFIG_X86_64
        .vread          = vread_hpet,
 #endif
@@ -750,10 +770,10 @@ static int hpet_clocksource_register(void)
        cycle_t t1;
 
        /* Start the counter */
-       hpet_start_counter();
+       hpet_restart_counter();
 
        /* Verify whether hpet counter works */
-       t1 = read_hpet();
+       t1 = hpet_readl(HPET_COUNTER);
        rdtscll(start);
 
        /*
@@ -767,7 +787,7 @@ static int hpet_clocksource_register(void)
                rdtscll(now);
        } while ((now - start) < 200000UL);
 
-       if (t1 == read_hpet()) {
+       if (t1 == hpet_readl(HPET_COUNTER)) {
                printk(KERN_WARNING
                       "HPET counter not counting. HPET disabled\n");
                return -ENODEV;