1
+ // SPDX-License-Identifier: GPL-2.0+
1
2
/*
2
3
* linux/arch/arm/plat-omap/dmtimer.c
3
4
*
15
16
*
16
17
* Copyright (C) 2009 Texas Instruments
17
18
* Added OMAP4 support - Santosh Shilimkar <[email protected] >
18
- *
19
- * This program is free software; you can redistribute it and/or modify it
20
- * under the terms of the GNU General Public License as published by the
21
- * Free Software Foundation; either version 2 of the License, or (at your
22
- * option) any later version.
23
- *
24
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
25
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
27
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
- *
33
- * You should have received a copy of the GNU General Public License along
34
- * with this program; if not, write to the Free Software Foundation, Inc.,
35
- * 675 Mass Ave, Cambridge, MA 02139, USA.
36
19
*/
37
20
38
21
#include <linux/clk.h>
39
22
#include <linux/clk-provider.h>
23
+ #include <linux/cpu_pm.h>
40
24
#include <linux/module.h>
41
25
#include <linux/io.h>
42
26
#include <linux/device.h>
@@ -109,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
109
93
timer -> context .tclr );
110
94
}
111
95
96
+ static void omap_timer_save_context (struct omap_dm_timer * timer )
97
+ {
98
+ timer -> context .tclr =
99
+ omap_dm_timer_read_reg (timer , OMAP_TIMER_CTRL_REG );
100
+ timer -> context .twer =
101
+ omap_dm_timer_read_reg (timer , OMAP_TIMER_WAKEUP_EN_REG );
102
+ timer -> context .tldr =
103
+ omap_dm_timer_read_reg (timer , OMAP_TIMER_LOAD_REG );
104
+ timer -> context .tmar =
105
+ omap_dm_timer_read_reg (timer , OMAP_TIMER_MATCH_REG );
106
+ timer -> context .tier = readl_relaxed (timer -> irq_ena );
107
+ timer -> context .tsicr =
108
+ omap_dm_timer_read_reg (timer , OMAP_TIMER_IF_CTRL_REG );
109
+ }
110
+
111
+ static int omap_timer_context_notifier (struct notifier_block * nb ,
112
+ unsigned long cmd , void * v )
113
+ {
114
+ struct omap_dm_timer * timer ;
115
+
116
+ timer = container_of (nb , struct omap_dm_timer , nb );
117
+
118
+ switch (cmd ) {
119
+ case CPU_CLUSTER_PM_ENTER :
120
+ if ((timer -> capability & OMAP_TIMER_ALWON ) ||
121
+ !atomic_read (& timer -> enabled ))
122
+ break ;
123
+ omap_timer_save_context (timer );
124
+ break ;
125
+ case CPU_CLUSTER_PM_ENTER_FAILED :
126
+ case CPU_CLUSTER_PM_EXIT :
127
+ if ((timer -> capability & OMAP_TIMER_ALWON ) ||
128
+ !atomic_read (& timer -> enabled ))
129
+ break ;
130
+ omap_timer_restore_context (timer );
131
+ break ;
132
+ }
133
+
134
+ return NOTIFY_OK ;
135
+ }
136
+
112
137
static int omap_dm_timer_reset (struct omap_dm_timer * timer )
113
138
{
114
139
u32 l , timeout = 100000 ;
@@ -225,21 +250,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
225
250
226
251
static void omap_dm_timer_enable (struct omap_dm_timer * timer )
227
252
{
228
- int c ;
229
-
230
253
pm_runtime_get_sync (& timer -> pdev -> dev );
231
-
232
- if (!(timer -> capability & OMAP_TIMER_ALWON )) {
233
- if (timer -> get_context_loss_count ) {
234
- c = timer -> get_context_loss_count (& timer -> pdev -> dev );
235
- if (c != timer -> ctx_loss_count ) {
236
- omap_timer_restore_context (timer );
237
- timer -> ctx_loss_count = c ;
238
- }
239
- } else {
240
- omap_timer_restore_context (timer );
241
- }
242
- }
243
254
}
244
255
245
256
static void omap_dm_timer_disable (struct omap_dm_timer * timer )
@@ -508,7 +519,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
508
519
509
520
int omap_dm_timer_trigger (struct omap_dm_timer * timer )
510
521
{
511
- if (unlikely (!timer || pm_runtime_suspended (& timer -> pdev -> dev ))) {
522
+ if (unlikely (!timer || ! atomic_read (& timer -> enabled ))) {
512
523
pr_err ("%s: timer not available or enabled.\n" , __func__ );
513
524
return - EINVAL ;
514
525
}
@@ -532,8 +543,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
532
543
omap_dm_timer_write_reg (timer , OMAP_TIMER_CTRL_REG , l );
533
544
}
534
545
535
- /* Save the context */
536
- timer -> context .tclr = l ;
537
546
return 0 ;
538
547
}
539
548
@@ -549,38 +558,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
549
558
550
559
__omap_dm_timer_stop (timer , timer -> posted , rate );
551
560
552
- /*
553
- * Since the register values are computed and written within
554
- * __omap_dm_timer_stop, we need to use read to retrieve the
555
- * context.
556
- */
557
- timer -> context .tclr =
558
- omap_dm_timer_read_reg (timer , OMAP_TIMER_CTRL_REG );
559
561
omap_dm_timer_disable (timer );
560
562
return 0 ;
561
563
}
562
564
563
- static int omap_dm_timer_set_load (struct omap_dm_timer * timer , int autoreload ,
565
+ static int omap_dm_timer_set_load (struct omap_dm_timer * timer ,
564
566
unsigned int load )
565
567
{
566
- u32 l ;
567
-
568
568
if (unlikely (!timer ))
569
569
return - EINVAL ;
570
570
571
571
omap_dm_timer_enable (timer );
572
- l = omap_dm_timer_read_reg (timer , OMAP_TIMER_CTRL_REG );
573
- if (autoreload )
574
- l |= OMAP_TIMER_CTRL_AR ;
575
- else
576
- l &= ~OMAP_TIMER_CTRL_AR ;
577
- omap_dm_timer_write_reg (timer , OMAP_TIMER_CTRL_REG , l );
578
572
omap_dm_timer_write_reg (timer , OMAP_TIMER_LOAD_REG , load );
579
573
580
- omap_dm_timer_write_reg (timer , OMAP_TIMER_TRIGGER_REG , 0 );
581
- /* Save the context */
582
- timer -> context .tclr = l ;
583
- timer -> context .tldr = load ;
584
574
omap_dm_timer_disable (timer );
585
575
return 0 ;
586
576
}
@@ -602,15 +592,12 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
602
592
omap_dm_timer_write_reg (timer , OMAP_TIMER_MATCH_REG , match );
603
593
omap_dm_timer_write_reg (timer , OMAP_TIMER_CTRL_REG , l );
604
594
605
- /* Save the context */
606
- timer -> context .tclr = l ;
607
- timer -> context .tmar = match ;
608
595
omap_dm_timer_disable (timer );
609
596
return 0 ;
610
597
}
611
598
612
599
static int omap_dm_timer_set_pwm (struct omap_dm_timer * timer , int def_on ,
613
- int toggle , int trigger )
600
+ int toggle , int trigger , int autoreload )
614
601
{
615
602
u32 l ;
616
603
@@ -620,20 +607,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
620
607
omap_dm_timer_enable (timer );
621
608
l = omap_dm_timer_read_reg (timer , OMAP_TIMER_CTRL_REG );
622
609
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
623
- OMAP_TIMER_CTRL_PT | (0x03 << 10 ));
610
+ OMAP_TIMER_CTRL_PT | (0x03 << 10 ) | OMAP_TIMER_CTRL_AR );
624
611
if (def_on )
625
612
l |= OMAP_TIMER_CTRL_SCPWM ;
626
613
if (toggle )
627
614
l |= OMAP_TIMER_CTRL_PT ;
628
615
l |= trigger << 10 ;
616
+ if (autoreload )
617
+ l |= OMAP_TIMER_CTRL_AR ;
629
618
omap_dm_timer_write_reg (timer , OMAP_TIMER_CTRL_REG , l );
630
619
631
- /* Save the context */
632
- timer -> context .tclr = l ;
633
620
omap_dm_timer_disable (timer );
634
621
return 0 ;
635
622
}
636
623
624
+ static int omap_dm_timer_get_pwm_status (struct omap_dm_timer * timer )
625
+ {
626
+ u32 l ;
627
+
628
+ if (unlikely (!timer ))
629
+ return - EINVAL ;
630
+
631
+ omap_dm_timer_enable (timer );
632
+ l = omap_dm_timer_read_reg (timer , OMAP_TIMER_CTRL_REG );
633
+ omap_dm_timer_disable (timer );
634
+
635
+ return l ;
636
+ }
637
+
637
638
static int omap_dm_timer_set_prescaler (struct omap_dm_timer * timer ,
638
639
int prescaler )
639
640
{
@@ -651,8 +652,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
651
652
}
652
653
omap_dm_timer_write_reg (timer , OMAP_TIMER_CTRL_REG , l );
653
654
654
- /* Save the context */
655
- timer -> context .tclr = l ;
656
655
omap_dm_timer_disable (timer );
657
656
return 0 ;
658
657
}
@@ -666,9 +665,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
666
665
omap_dm_timer_enable (timer );
667
666
__omap_dm_timer_int_enable (timer , value );
668
667
669
- /* Save the context */
670
- timer -> context .tier = value ;
671
- timer -> context .twer = value ;
672
668
omap_dm_timer_disable (timer );
673
669
return 0 ;
674
670
}
@@ -696,9 +692,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
696
692
l = omap_dm_timer_read_reg (timer , OMAP_TIMER_WAKEUP_EN_REG ) & ~mask ;
697
693
omap_dm_timer_write_reg (timer , OMAP_TIMER_WAKEUP_EN_REG , l );
698
694
699
- /* Save the context */
700
- timer -> context .tier &= ~mask ;
701
- timer -> context .twer &= ~mask ;
702
695
omap_dm_timer_disable (timer );
703
696
return 0 ;
704
697
}
@@ -707,7 +700,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
707
700
{
708
701
unsigned int l ;
709
702
710
- if (unlikely (!timer || pm_runtime_suspended (& timer -> pdev -> dev ))) {
703
+ if (unlikely (!timer || ! atomic_read (& timer -> enabled ))) {
711
704
pr_err ("%s: timer not available or enabled.\n" , __func__ );
712
705
return 0 ;
713
706
}
@@ -719,7 +712,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
719
712
720
713
static int omap_dm_timer_write_status (struct omap_dm_timer * timer , unsigned int value )
721
714
{
722
- if (unlikely (!timer || pm_runtime_suspended (& timer -> pdev -> dev )))
715
+ if (unlikely (!timer || ! atomic_read (& timer -> enabled )))
723
716
return - EINVAL ;
724
717
725
718
__omap_dm_timer_write_status (timer , value );
@@ -729,7 +722,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int
729
722
730
723
static unsigned int omap_dm_timer_read_counter (struct omap_dm_timer * timer )
731
724
{
732
- if (unlikely (!timer || pm_runtime_suspended (& timer -> pdev -> dev ))) {
725
+ if (unlikely (!timer || ! atomic_read (& timer -> enabled ))) {
733
726
pr_err ("%s: timer not iavailable or enabled.\n" , __func__ );
734
727
return 0 ;
735
728
}
@@ -739,7 +732,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
739
732
740
733
static int omap_dm_timer_write_counter (struct omap_dm_timer * timer , unsigned int value )
741
734
{
742
- if (unlikely (!timer || pm_runtime_suspended (& timer -> pdev -> dev ))) {
735
+ if (unlikely (!timer || ! atomic_read (& timer -> enabled ))) {
743
736
pr_err ("%s: timer not available or enabled.\n" , __func__ );
744
737
return - EINVAL ;
745
738
}
@@ -767,6 +760,37 @@ int omap_dm_timers_active(void)
767
760
return 0 ;
768
761
}
769
762
763
+ static int __maybe_unused omap_dm_timer_runtime_suspend (struct device * dev )
764
+ {
765
+ struct omap_dm_timer * timer = dev_get_drvdata (dev );
766
+
767
+ atomic_set (& timer -> enabled , 0 );
768
+
769
+ if (timer -> capability & OMAP_TIMER_ALWON || !timer -> func_base )
770
+ return 0 ;
771
+
772
+ omap_timer_save_context (timer );
773
+
774
+ return 0 ;
775
+ }
776
+
777
+ static int __maybe_unused omap_dm_timer_runtime_resume (struct device * dev )
778
+ {
779
+ struct omap_dm_timer * timer = dev_get_drvdata (dev );
780
+
781
+ if (!(timer -> capability & OMAP_TIMER_ALWON ) && timer -> func_base )
782
+ omap_timer_restore_context (timer );
783
+
784
+ atomic_set (& timer -> enabled , 1 );
785
+
786
+ return 0 ;
787
+ }
788
+
789
+ static const struct dev_pm_ops omap_dm_timer_pm_ops = {
790
+ SET_RUNTIME_PM_OPS (omap_dm_timer_runtime_suspend ,
791
+ omap_dm_timer_runtime_resume , NULL )
792
+ };
793
+
770
794
static const struct of_device_id omap_timer_match [];
771
795
772
796
/**
@@ -808,6 +832,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
808
832
if (IS_ERR (timer -> io_base ))
809
833
return PTR_ERR (timer -> io_base );
810
834
835
+ platform_set_drvdata (pdev , timer );
836
+
811
837
if (dev -> of_node ) {
812
838
if (of_find_property (dev -> of_node , "ti,timer-alwon" , NULL ))
813
839
timer -> capability |= OMAP_TIMER_ALWON ;
@@ -821,7 +847,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
821
847
timer -> id = pdev -> id ;
822
848
timer -> capability = pdata -> timer_capability ;
823
849
timer -> reserved = omap_dm_timer_reserved_systimer (timer -> id );
824
- timer -> get_context_loss_count = pdata -> get_context_loss_count ;
850
+ }
851
+
852
+ if (!(timer -> capability & OMAP_TIMER_ALWON )) {
853
+ timer -> nb .notifier_call = omap_timer_context_notifier ;
854
+ cpu_pm_register_notifier (& timer -> nb );
825
855
}
826
856
827
857
if (pdata )
@@ -875,6 +905,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
875
905
list_for_each_entry (timer , & omap_timer_list , node )
876
906
if (!strcmp (dev_name (& timer -> pdev -> dev ),
877
907
dev_name (& pdev -> dev ))) {
908
+ if (!(timer -> capability & OMAP_TIMER_ALWON ))
909
+ cpu_pm_unregister_notifier (& timer -> nb );
878
910
list_del (& timer -> node );
879
911
ret = 0 ;
880
912
break ;
@@ -903,6 +935,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = {
903
935
.set_load = omap_dm_timer_set_load ,
904
936
.set_match = omap_dm_timer_set_match ,
905
937
.set_pwm = omap_dm_timer_set_pwm ,
938
+ .get_pwm_status = omap_dm_timer_get_pwm_status ,
906
939
.set_prescaler = omap_dm_timer_set_prescaler ,
907
940
.read_counter = omap_dm_timer_read_counter ,
908
941
.write_counter = omap_dm_timer_write_counter ,
@@ -953,6 +986,7 @@ static struct platform_driver omap_dm_timer_driver = {
953
986
.driver = {
954
987
.name = "omap_timer" ,
955
988
.of_match_table = of_match_ptr (omap_timer_match ),
989
+ .pm = & omap_dm_timer_pm_ops ,
956
990
},
957
991
};
958
992
0 commit comments