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.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 08d0c418c94a..0965e9848b3d 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -37,6 +37,7 @@
37 37
38struct sh_cmt_priv { 38struct sh_cmt_priv {
39 void __iomem *mapbase; 39 void __iomem *mapbase;
40 void __iomem *mapbase_str;
40 struct clk *clk; 41 struct clk *clk;
41 unsigned long width; /* 16 or 32 bit version of hardware block */ 42 unsigned long width; /* 16 or 32 bit version of hardware block */
42 unsigned long overflow_bit; 43 unsigned long overflow_bit;
@@ -79,6 +80,12 @@ struct sh_cmt_priv {
79 * CMCSR 0xffca0060 16-bit 80 * CMCSR 0xffca0060 16-bit
80 * CMCNT 0xffca0064 32-bit 81 * CMCNT 0xffca0064 32-bit
81 * CMCOR 0xffca0068 32-bit 82 * CMCOR 0xffca0068 32-bit
83 *
84 * "32-bit counter and 32-bit control" as found on r8a73a4 and r8a7790:
85 * CMSTR 0xffca0500 32-bit
86 * CMCSR 0xffca0510 32-bit
87 * CMCNT 0xffca0514 32-bit
88 * CMCOR 0xffca0518 32-bit
82 */ 89 */
83 90
84static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs) 91static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
@@ -109,9 +116,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
109 116
110static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p) 117static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
111{ 118{
112 struct sh_timer_config *cfg = p->pdev->dev.platform_data; 119 return p->read_control(p->mapbase_str, 0);
113
114 return p->read_control(p->mapbase - cfg->channel_offset, 0);
115} 120}
116 121
117static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p) 122static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
@@ -127,9 +132,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
127static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p, 132static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
128 unsigned long value) 133 unsigned long value)
129{ 134{
130 struct sh_timer_config *cfg = p->pdev->dev.platform_data; 135 p->write_control(p->mapbase_str, 0, value);
131
132 p->write_control(p->mapbase - cfg->channel_offset, 0, value);
133} 136}
134 137
135static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p, 138static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
@@ -676,7 +679,7 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
676static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) 679static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
677{ 680{
678 struct sh_timer_config *cfg = pdev->dev.platform_data; 681 struct sh_timer_config *cfg = pdev->dev.platform_data;
679 struct resource *res; 682 struct resource *res, *res2;
680 int irq, ret; 683 int irq, ret;
681 ret = -ENXIO; 684 ret = -ENXIO;
682 685
@@ -694,6 +697,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
694 goto err0; 697 goto err0;
695 } 698 }
696 699
700 /* optional resource for the shared timer start/stop register */
701 res2 = platform_get_resource(p->pdev, IORESOURCE_MEM, 1);
702
697 irq = platform_get_irq(p->pdev, 0); 703 irq = platform_get_irq(p->pdev, 0);
698 if (irq < 0) { 704 if (irq < 0) {
699 dev_err(&p->pdev->dev, "failed to get irq\n"); 705 dev_err(&p->pdev->dev, "failed to get irq\n");
@@ -707,6 +713,15 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
707 goto err0; 713 goto err0;
708 } 714 }
709 715
716 /* map second resource for CMSTR */
717 p->mapbase_str = ioremap_nocache(res2 ? res2->start :
718 res->start - cfg->channel_offset,
719 res2 ? resource_size(res2) : 2);
720 if (p->mapbase_str == NULL) {
721 dev_err(&p->pdev->dev, "failed to remap I/O second memory\n");
722 goto err1;
723 }
724
710 /* request irq using setup_irq() (too early for request_irq()) */ 725 /* request irq using setup_irq() (too early for request_irq()) */
711 p->irqaction.name = dev_name(&p->pdev->dev); 726 p->irqaction.name = dev_name(&p->pdev->dev);
712 p->irqaction.handler = sh_cmt_interrupt; 727 p->irqaction.handler = sh_cmt_interrupt;
@@ -719,11 +734,17 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
719 if (IS_ERR(p->clk)) { 734 if (IS_ERR(p->clk)) {
720 dev_err(&p->pdev->dev, "cannot get clock\n"); 735 dev_err(&p->pdev->dev, "cannot get clock\n");
721 ret = PTR_ERR(p->clk); 736 ret = PTR_ERR(p->clk);
722 goto err1; 737 goto err2;
723 } 738 }
724 739
725 p->read_control = sh_cmt_read16; 740 if (res2 && (resource_size(res2) == 4)) {
726 p->write_control = sh_cmt_write16; 741 /* assume both CMSTR and CMCSR to be 32-bit */
742 p->read_control = sh_cmt_read32;
743 p->write_control = sh_cmt_write32;
744 } else {
745 p->read_control = sh_cmt_read16;
746 p->write_control = sh_cmt_write16;
747 }
727 748
728 if (resource_size(res) == 6) { 749 if (resource_size(res) == 6) {
729 p->width = 16; 750 p->width = 16;
@@ -752,22 +773,23 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
752 cfg->clocksource_rating); 773 cfg->clocksource_rating);
753 if (ret) { 774 if (ret) {
754 dev_err(&p->pdev->dev, "registration failed\n"); 775 dev_err(&p->pdev->dev, "registration failed\n");
755 goto err2; 776 goto err3;
756 } 777 }
757 p->cs_enabled = false; 778 p->cs_enabled = false;
758 779
759 ret = setup_irq(irq, &p->irqaction); 780 ret = setup_irq(irq, &p->irqaction);
760 if (ret) { 781 if (ret) {
761 dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); 782 dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
762 goto err2; 783 goto err3;
763 } 784 }
764 785
765 platform_set_drvdata(pdev, p); 786 platform_set_drvdata(pdev, p);
766 787
767 return 0; 788 return 0;
768err2: 789err3:
769 clk_put(p->clk); 790 clk_put(p->clk);
770 791err2:
792 iounmap(p->mapbase_str);
771err1: 793err1:
772 iounmap(p->mapbase); 794 iounmap(p->mapbase);
773err0: 795err0: