aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/sh_cmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource/sh_cmt.c')
-rw-r--r--drivers/clocksource/sh_cmt.c68
1 files changed, 27 insertions, 41 deletions
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 6b3e0c2f33e2..744f748cc84b 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -29,6 +29,7 @@
29#include <linux/clocksource.h> 29#include <linux/clocksource.h>
30#include <linux/clockchips.h> 30#include <linux/clockchips.h>
31#include <linux/sh_timer.h> 31#include <linux/sh_timer.h>
32#include <linux/slab.h>
32 33
33struct sh_cmt_priv { 34struct sh_cmt_priv {
34 void __iomem *mapbase; 35 void __iomem *mapbase;
@@ -40,7 +41,6 @@ struct sh_cmt_priv {
40 struct platform_device *pdev; 41 struct platform_device *pdev;
41 42
42 unsigned long flags; 43 unsigned long flags;
43 unsigned long flags_suspend;
44 unsigned long match_value; 44 unsigned long match_value;
45 unsigned long next_match_value; 45 unsigned long next_match_value;
46 unsigned long max_match_value; 46 unsigned long max_match_value;
@@ -432,6 +432,11 @@ static void sh_cmt_clocksource_disable(struct clocksource *cs)
432 sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE); 432 sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
433} 433}
434 434
435static void sh_cmt_clocksource_resume(struct clocksource *cs)
436{
437 sh_cmt_start(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
438}
439
435static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, 440static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
436 char *name, unsigned long rating) 441 char *name, unsigned long rating)
437{ 442{
@@ -442,6 +447,8 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
442 cs->read = sh_cmt_clocksource_read; 447 cs->read = sh_cmt_clocksource_read;
443 cs->enable = sh_cmt_clocksource_enable; 448 cs->enable = sh_cmt_clocksource_enable;
444 cs->disable = sh_cmt_clocksource_disable; 449 cs->disable = sh_cmt_clocksource_disable;
450 cs->suspend = sh_cmt_clocksource_disable;
451 cs->resume = sh_cmt_clocksource_resume;
445 cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); 452 cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
446 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 453 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
447 pr_info("sh_cmt: %s used as clock source\n", cs->name); 454 pr_info("sh_cmt: %s used as clock source\n", cs->name);
@@ -603,18 +610,13 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
603 p->irqaction.handler = sh_cmt_interrupt; 610 p->irqaction.handler = sh_cmt_interrupt;
604 p->irqaction.dev_id = p; 611 p->irqaction.dev_id = p;
605 p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; 612 p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
606 ret = setup_irq(irq, &p->irqaction);
607 if (ret) {
608 pr_err("sh_cmt: failed to request irq %d\n", irq);
609 goto err1;
610 }
611 613
612 /* get hold of clock */ 614 /* get hold of clock */
613 p->clk = clk_get(&p->pdev->dev, cfg->clk); 615 p->clk = clk_get(&p->pdev->dev, cfg->clk);
614 if (IS_ERR(p->clk)) { 616 if (IS_ERR(p->clk)) {
615 pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); 617 pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
616 ret = PTR_ERR(p->clk); 618 ret = PTR_ERR(p->clk);
617 goto err2; 619 goto err1;
618 } 620 }
619 621
620 if (resource_size(res) == 6) { 622 if (resource_size(res) == 6) {
@@ -627,14 +629,25 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
627 p->clear_bits = ~0xc000; 629 p->clear_bits = ~0xc000;
628 } 630 }
629 631
630 return sh_cmt_register(p, cfg->name, 632 ret = sh_cmt_register(p, cfg->name,
631 cfg->clockevent_rating, 633 cfg->clockevent_rating,
632 cfg->clocksource_rating); 634 cfg->clocksource_rating);
633 err2: 635 if (ret) {
634 remove_irq(irq, &p->irqaction); 636 pr_err("sh_cmt: registration failed\n");
635 err1: 637 goto err1;
638 }
639
640 ret = setup_irq(irq, &p->irqaction);
641 if (ret) {
642 pr_err("sh_cmt: failed to request irq %d\n", irq);
643 goto err1;
644 }
645
646 return 0;
647
648err1:
636 iounmap(p->mapbase); 649 iounmap(p->mapbase);
637 err0: 650err0:
638 return ret; 651 return ret;
639} 652}
640 653
@@ -668,38 +681,11 @@ static int __devexit sh_cmt_remove(struct platform_device *pdev)
668 return -EBUSY; /* cannot unregister clockevent and clocksource */ 681 return -EBUSY; /* cannot unregister clockevent and clocksource */
669} 682}
670 683
671static int sh_cmt_suspend(struct device *dev)
672{
673 struct platform_device *pdev = to_platform_device(dev);
674 struct sh_cmt_priv *p = platform_get_drvdata(pdev);
675
676 /* save flag state and stop CMT channel */
677 p->flags_suspend = p->flags;
678 sh_cmt_stop(p, p->flags);
679 return 0;
680}
681
682static int sh_cmt_resume(struct device *dev)
683{
684 struct platform_device *pdev = to_platform_device(dev);
685 struct sh_cmt_priv *p = platform_get_drvdata(pdev);
686
687 /* start CMT channel from saved state */
688 sh_cmt_start(p, p->flags_suspend);
689 return 0;
690}
691
692static struct dev_pm_ops sh_cmt_dev_pm_ops = {
693 .suspend = sh_cmt_suspend,
694 .resume = sh_cmt_resume,
695};
696
697static struct platform_driver sh_cmt_device_driver = { 684static struct platform_driver sh_cmt_device_driver = {
698 .probe = sh_cmt_probe, 685 .probe = sh_cmt_probe,
699 .remove = __devexit_p(sh_cmt_remove), 686 .remove = __devexit_p(sh_cmt_remove),
700 .driver = { 687 .driver = {
701 .name = "sh_cmt", 688 .name = "sh_cmt",
702 .pm = &sh_cmt_dev_pm_ops,
703 } 689 }
704}; 690};
705 691