]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
x86/hpet: Migrate to new set_state interface
authorViresh Kumar <viresh.kumar@linaro.org>
Thu, 16 Jul 2015 10:58:45 +0000 (16:28 +0530)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 30 Jul 2015 19:28:25 +0000 (21:28 +0200)
Migrate hpet driver to the new 'set-state' interface provided by
clockevents core, the earlier 'set-mode' interface is marked obsolete
now.

This also enables us to implement callbacks for new states of clockevent
devices, for example: ONESHOT_STOPPED.

Forward definition of 'hpet_clockevent' wasn't required and so it is
placed after all the callback are defined, to avoid forward declaring
all the callbacks.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Cc: linaro-kernel@lists.linaro.org
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Link: http://lkml.kernel.org/r/8cc9864b6d6342dfac28f270cf69f4cba46fffae.1437042675.git.viresh.kumar@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/kernel/hpet.c

index 10757d0a3fcf438e43ffbfc634e7daa8dc110a2e..437297ac96d059357b92ff94fd7f86111661d9be 100644 (file)
@@ -226,22 +226,7 @@ static void hpet_reserve_platform_timers(unsigned int id) { }
  */
 static unsigned long hpet_freq;
 
-static void hpet_legacy_set_mode(enum clock_event_mode mode,
-                         struct clock_event_device *evt);
-static int hpet_legacy_next_event(unsigned long delta,
-                          struct clock_event_device *evt);
-
-/*
- * The hpet clock event device
- */
-static struct clock_event_device hpet_clockevent = {
-       .name           = "hpet",
-       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .set_mode       = hpet_legacy_set_mode,
-       .set_next_event = hpet_legacy_next_event,
-       .irq            = 0,
-       .rating         = 50,
-};
+static struct clock_event_device hpet_clockevent;
 
 static void hpet_stop_counter(void)
 {
@@ -306,64 +291,74 @@ static void hpet_legacy_clockevent_register(void)
        printk(KERN_DEBUG "hpet clockevent registered\n");
 }
 
-static void hpet_set_mode(enum clock_event_mode mode,
-                         struct clock_event_device *evt, int timer)
+static int hpet_set_periodic(struct clock_event_device *evt, int timer)
 {
        unsigned int cfg, cmp, now;
        uint64_t delta;
 
-       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);
-               cmp = now + (unsigned int) delta;
-               cfg = hpet_readl(HPET_Tn_CFG(timer));
-               cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
-                      HPET_TN_SETVAL | HPET_TN_32BIT;
-               hpet_writel(cfg, HPET_Tn_CFG(timer));
-               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 int) delta, HPET_Tn_CMP(timer));
-               hpet_start_counter();
-               hpet_print_config();
-               break;
+       hpet_stop_counter();
+       delta = ((uint64_t)(NSEC_PER_SEC / HZ)) * evt->mult;
+       delta >>= evt->shift;
+       now = hpet_readl(HPET_COUNTER);
+       cmp = now + (unsigned int)delta;
+       cfg = hpet_readl(HPET_Tn_CFG(timer));
+       cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+              HPET_TN_32BIT;
+       hpet_writel(cfg, HPET_Tn_CFG(timer));
+       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 int)delta, HPET_Tn_CMP(timer));
+       hpet_start_counter();
+       hpet_print_config();
 
-       case CLOCK_EVT_MODE_ONESHOT:
-               cfg = hpet_readl(HPET_Tn_CFG(timer));
-               cfg &= ~HPET_TN_PERIODIC;
-               cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-               hpet_writel(cfg, HPET_Tn_CFG(timer));
-               break;
+       return 0;
+}
 
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               cfg = hpet_readl(HPET_Tn_CFG(timer));
-               cfg &= ~HPET_TN_ENABLE;
-               hpet_writel(cfg, HPET_Tn_CFG(timer));
-               break;
+static int hpet_set_oneshot(struct clock_event_device *evt, int timer)
+{
+       unsigned int cfg;
 
-       case CLOCK_EVT_MODE_RESUME:
-               if (timer == 0) {
-                       hpet_enable_legacy_int();
-               } else {
-                       struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-                       irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
-                       disable_irq(hdev->irq);
-                       irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
-                       enable_irq(hdev->irq);
-               }
-               hpet_print_config();
-               break;
+       cfg = hpet_readl(HPET_Tn_CFG(timer));
+       cfg &= ~HPET_TN_PERIODIC;
+       cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+       hpet_writel(cfg, HPET_Tn_CFG(timer));
+
+       return 0;
+}
+
+static int hpet_shutdown(struct clock_event_device *evt, int timer)
+{
+       unsigned int cfg;
+
+       cfg = hpet_readl(HPET_Tn_CFG(timer));
+       cfg &= ~HPET_TN_ENABLE;
+       hpet_writel(cfg, HPET_Tn_CFG(timer));
+
+       return 0;
+}
+
+static int hpet_resume(struct clock_event_device *evt, int timer)
+{
+       if (!timer) {
+               hpet_enable_legacy_int();
+       } else {
+               struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
+
+               irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
+               disable_irq(hdev->irq);
+               irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
+               enable_irq(hdev->irq);
        }
+       hpet_print_config();
+
+       return 0;
 }
 
 static int hpet_next_event(unsigned long delta,
@@ -403,10 +398,24 @@ static int hpet_next_event(unsigned long delta,
        return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
-static void hpet_legacy_set_mode(enum clock_event_mode mode,
-                       struct clock_event_device *evt)
+static int hpet_legacy_shutdown(struct clock_event_device *evt)
+{
+       return hpet_shutdown(evt, 0);
+}
+
+static int hpet_legacy_set_oneshot(struct clock_event_device *evt)
+{
+       return hpet_set_oneshot(evt, 0);
+}
+
+static int hpet_legacy_set_periodic(struct clock_event_device *evt)
 {
-       hpet_set_mode(mode, evt, 0);
+       return hpet_set_periodic(evt, 0);
+}
+
+static int hpet_legacy_resume(struct clock_event_device *evt)
+{
+       return hpet_resume(evt, 0);
 }
 
 static int hpet_legacy_next_event(unsigned long delta,
@@ -415,6 +424,22 @@ static int hpet_legacy_next_event(unsigned long delta,
        return hpet_next_event(delta, evt, 0);
 }
 
+/*
+ * The hpet clock event device
+ */
+static struct clock_event_device hpet_clockevent = {
+       .name                   = "hpet",
+       .features               = CLOCK_EVT_FEAT_PERIODIC |
+                                 CLOCK_EVT_FEAT_ONESHOT,
+       .set_state_periodic     = hpet_legacy_set_periodic,
+       .set_state_oneshot      = hpet_legacy_set_oneshot,
+       .set_state_shutdown     = hpet_legacy_shutdown,
+       .tick_resume            = hpet_legacy_resume,
+       .set_next_event         = hpet_legacy_next_event,
+       .irq                    = 0,
+       .rating                 = 50,
+};
+
 /*
  * HPET MSI Support
  */
@@ -459,11 +484,32 @@ void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg)
        msg->address_hi = 0;
 }
 
-static void hpet_msi_set_mode(enum clock_event_mode mode,
-                               struct clock_event_device *evt)
+static int hpet_msi_shutdown(struct clock_event_device *evt)
+{
+       struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
+
+       return hpet_shutdown(evt, hdev->num);
+}
+
+static int hpet_msi_set_oneshot(struct clock_event_device *evt)
+{
+       struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
+
+       return hpet_set_oneshot(evt, hdev->num);
+}
+
+static int hpet_msi_set_periodic(struct clock_event_device *evt)
 {
        struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-       hpet_set_mode(mode, evt, hdev->num);
+
+       return hpet_set_periodic(evt, hdev->num);
+}
+
+static int hpet_msi_resume(struct clock_event_device *evt)
+{
+       struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
+
+       return hpet_resume(evt, hdev->num);
 }
 
 static int hpet_msi_next_event(unsigned long delta,
@@ -523,10 +569,14 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 
        evt->rating = 110;
        evt->features = CLOCK_EVT_FEAT_ONESHOT;
-       if (hdev->flags & HPET_DEV_PERI_CAP)
+       if (hdev->flags & HPET_DEV_PERI_CAP) {
                evt->features |= CLOCK_EVT_FEAT_PERIODIC;
+               evt->set_state_periodic = hpet_msi_set_periodic;
+       }
 
-       evt->set_mode = hpet_msi_set_mode;
+       evt->set_state_shutdown = hpet_msi_shutdown;
+       evt->set_state_oneshot = hpet_msi_set_oneshot;
+       evt->tick_resume = hpet_msi_resume;
        evt->set_next_event = hpet_msi_next_event;
        evt->cpumask = cpumask_of(hdev->cpu);