OMAP: DSS2: Make check-delay-loops consistent
[safe/jmp/linux-2.6] / drivers / clocksource / sh_cmt.c
index aeb8c9b..6b3e0c2 100644 (file)
@@ -40,6 +40,7 @@ struct sh_cmt_priv {
        struct platform_device *pdev;
 
        unsigned long flags;
+       unsigned long flags_suspend;
        unsigned long match_value;
        unsigned long next_match_value;
        unsigned long max_match_value;
@@ -184,6 +185,9 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)
        /* disable channel */
        sh_cmt_start_stop_ch(p, 0);
 
+       /* disable interrupts in CMT block */
+       sh_cmt_write(p, CMCSR, 0);
+
        /* stop clock */
        clk_disable(p->clk);
 }
@@ -537,9 +541,9 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
        clockevents_register_device(ced);
 }
 
-int sh_cmt_register(struct sh_cmt_priv *p, char *name,
-                   unsigned long clockevent_rating,
-                   unsigned long clocksource_rating)
+static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
+                          unsigned long clockevent_rating,
+                          unsigned long clocksource_rating)
 {
        if (p->width == (sizeof(p->max_match_value) * 8))
                p->max_match_value = ~0;
@@ -599,7 +603,6 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
        p->irqaction.handler = sh_cmt_interrupt;
        p->irqaction.dev_id = p;
        p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
-       p->irqaction.mask = CPU_MASK_NONE;
        ret = setup_irq(irq, &p->irqaction);
        if (ret) {
                pr_err("sh_cmt: failed to request irq %d\n", irq);
@@ -665,11 +668,38 @@ static int __devexit sh_cmt_remove(struct platform_device *pdev)
        return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
+static int sh_cmt_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+
+       /* save flag state and stop CMT channel */
+       p->flags_suspend = p->flags;
+       sh_cmt_stop(p, p->flags);
+       return 0;
+}
+
+static int sh_cmt_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+
+       /* start CMT channel from saved state */
+       sh_cmt_start(p, p->flags_suspend);
+       return 0;
+}
+
+static struct dev_pm_ops sh_cmt_dev_pm_ops = {
+       .suspend = sh_cmt_suspend,
+       .resume = sh_cmt_resume,
+};
+
 static struct platform_driver sh_cmt_device_driver = {
        .probe          = sh_cmt_probe,
        .remove         = __devexit_p(sh_cmt_remove),
        .driver         = {
                .name   = "sh_cmt",
+               .pm     = &sh_cmt_dev_pm_ops,
        }
 };