hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/clocksource/timer-ti-dm.c
....@@ -1,9 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * linux/arch/arm/plat-omap/dmtimer.c
34 *
45 * OMAP Dual-Mode Timers
56 *
6
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
7
+ * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com/
78 * Tarun Kanti DebBarma <tarun.kanti@ti.com>
89 * Thara Gopinath <thara@ti.com>
910 *
....@@ -15,28 +16,11 @@
1516 *
1617 * Copyright (C) 2009 Texas Instruments
1718 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
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.
3619 */
3720
3821 #include <linux/clk.h>
3922 #include <linux/clk-provider.h>
23
+#include <linux/cpu_pm.h>
4024 #include <linux/module.h>
4125 #include <linux/io.h>
4226 #include <linux/device.h>
....@@ -94,6 +78,9 @@
9478
9579 static void omap_timer_restore_context(struct omap_dm_timer *timer)
9680 {
81
+ __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET,
82
+ timer->context.ocp_cfg, 0);
83
+
9784 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
9885 timer->context.twer);
9986 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
....@@ -107,6 +94,50 @@
10794 writel_relaxed(timer->context.tier, timer->irq_ena);
10895 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
10996 timer->context.tclr);
97
+}
98
+
99
+static void omap_timer_save_context(struct omap_dm_timer *timer)
100
+{
101
+ timer->context.ocp_cfg =
102
+ __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
103
+
104
+ timer->context.tclr =
105
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
106
+ timer->context.twer =
107
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG);
108
+ timer->context.tldr =
109
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG);
110
+ timer->context.tmar =
111
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG);
112
+ timer->context.tier = readl_relaxed(timer->irq_ena);
113
+ timer->context.tsicr =
114
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG);
115
+}
116
+
117
+static int omap_timer_context_notifier(struct notifier_block *nb,
118
+ unsigned long cmd, void *v)
119
+{
120
+ struct omap_dm_timer *timer;
121
+
122
+ timer = container_of(nb, struct omap_dm_timer, nb);
123
+
124
+ switch (cmd) {
125
+ case CPU_CLUSTER_PM_ENTER:
126
+ if ((timer->capability & OMAP_TIMER_ALWON) ||
127
+ !atomic_read(&timer->enabled))
128
+ break;
129
+ omap_timer_save_context(timer);
130
+ break;
131
+ case CPU_CLUSTER_PM_ENTER_FAILED:
132
+ case CPU_CLUSTER_PM_EXIT:
133
+ if ((timer->capability & OMAP_TIMER_ALWON) ||
134
+ !atomic_read(&timer->enabled))
135
+ break;
136
+ omap_timer_restore_context(timer);
137
+ break;
138
+ }
139
+
140
+ return NOTIFY_OK;
110141 }
111142
112143 static int omap_dm_timer_reset(struct omap_dm_timer *timer)
....@@ -136,35 +167,6 @@
136167 timer->posted = 0;
137168
138169 return 0;
139
-}
140
-
141
-static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
142
-{
143
- int ret;
144
- struct clk *parent;
145
-
146
- /*
147
- * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
148
- * do not call clk_get() for these devices.
149
- */
150
- if (!timer->fclk)
151
- return -ENODEV;
152
-
153
- parent = clk_get(&timer->pdev->dev, NULL);
154
- if (IS_ERR(parent))
155
- return -ENODEV;
156
-
157
- /* Bail out if both clocks point to fck */
158
- if (clk_is_match(parent, timer->fclk))
159
- return 0;
160
-
161
- ret = clk_set_parent(timer->fclk, parent);
162
- if (ret < 0)
163
- pr_err("%s: failed to set parent\n", __func__);
164
-
165
- clk_put(parent);
166
-
167
- return ret;
168170 }
169171
170172 static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
....@@ -225,21 +227,7 @@
225227
226228 static void omap_dm_timer_enable(struct omap_dm_timer *timer)
227229 {
228
- int c;
229
-
230230 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
- }
243231 }
244232
245233 static void omap_dm_timer_disable(struct omap_dm_timer *timer)
....@@ -276,11 +264,7 @@
276264 __omap_dm_timer_enable_posted(timer);
277265 omap_dm_timer_disable(timer);
278266
279
- rc = omap_dm_timer_of_set_source(timer);
280
- if (rc == -ENODEV)
281
- return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
282
-
283
- return rc;
267
+ return 0;
284268 }
285269
286270 static inline u32 omap_dm_timer_reserved_systimer(int id)
....@@ -508,7 +492,7 @@
508492
509493 int omap_dm_timer_trigger(struct omap_dm_timer *timer)
510494 {
511
- if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
495
+ if (unlikely(!timer || !atomic_read(&timer->enabled))) {
512496 pr_err("%s: timer not available or enabled.\n", __func__);
513497 return -EINVAL;
514498 }
....@@ -532,8 +516,6 @@
532516 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
533517 }
534518
535
- /* Save the context */
536
- timer->context.tclr = l;
537519 return 0;
538520 }
539521
....@@ -549,70 +531,23 @@
549531
550532 __omap_dm_timer_stop(timer, timer->posted, rate);
551533
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);
559534 omap_dm_timer_disable(timer);
560535 return 0;
561536 }
562537
563
-static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
538
+static int omap_dm_timer_set_load(struct omap_dm_timer *timer,
564539 unsigned int load)
565540 {
566
- u32 l;
567
-
568541 if (unlikely(!timer))
569542 return -EINVAL;
570543
571544 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);
578545 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
579546
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;
584547 omap_dm_timer_disable(timer);
585548 return 0;
586549 }
587550
588
-/* Optimized set_load which removes costly spin wait in timer_start */
589
-int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
590
- unsigned int load)
591
-{
592
- u32 l;
593
-
594
- if (unlikely(!timer))
595
- return -EINVAL;
596
-
597
- omap_dm_timer_enable(timer);
598
-
599
- l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
600
- if (autoreload) {
601
- l |= OMAP_TIMER_CTRL_AR;
602
- omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
603
- } else {
604
- l &= ~OMAP_TIMER_CTRL_AR;
605
- }
606
- l |= OMAP_TIMER_CTRL_ST;
607
-
608
- __omap_dm_timer_load_start(timer, l, load, timer->posted);
609
-
610
- /* Save the context */
611
- timer->context.tclr = l;
612
- timer->context.tldr = load;
613
- timer->context.tcrr = load;
614
- return 0;
615
-}
616551 static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
617552 unsigned int match)
618553 {
....@@ -630,15 +565,12 @@
630565 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
631566 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
632567
633
- /* Save the context */
634
- timer->context.tclr = l;
635
- timer->context.tmar = match;
636568 omap_dm_timer_disable(timer);
637569 return 0;
638570 }
639571
640572 static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
641
- int toggle, int trigger)
573
+ int toggle, int trigger, int autoreload)
642574 {
643575 u32 l;
644576
....@@ -648,18 +580,32 @@
648580 omap_dm_timer_enable(timer);
649581 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
650582 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
651
- OMAP_TIMER_CTRL_PT | (0x03 << 10));
583
+ OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR);
652584 if (def_on)
653585 l |= OMAP_TIMER_CTRL_SCPWM;
654586 if (toggle)
655587 l |= OMAP_TIMER_CTRL_PT;
656588 l |= trigger << 10;
589
+ if (autoreload)
590
+ l |= OMAP_TIMER_CTRL_AR;
657591 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
658592
659
- /* Save the context */
660
- timer->context.tclr = l;
661593 omap_dm_timer_disable(timer);
662594 return 0;
595
+}
596
+
597
+static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer)
598
+{
599
+ u32 l;
600
+
601
+ if (unlikely(!timer))
602
+ return -EINVAL;
603
+
604
+ omap_dm_timer_enable(timer);
605
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
606
+ omap_dm_timer_disable(timer);
607
+
608
+ return l;
663609 }
664610
665611 static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
....@@ -679,8 +625,6 @@
679625 }
680626 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
681627
682
- /* Save the context */
683
- timer->context.tclr = l;
684628 omap_dm_timer_disable(timer);
685629 return 0;
686630 }
....@@ -694,9 +638,6 @@
694638 omap_dm_timer_enable(timer);
695639 __omap_dm_timer_int_enable(timer, value);
696640
697
- /* Save the context */
698
- timer->context.tier = value;
699
- timer->context.twer = value;
700641 omap_dm_timer_disable(timer);
701642 return 0;
702643 }
....@@ -724,9 +665,6 @@
724665 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
725666 omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
726667
727
- /* Save the context */
728
- timer->context.tier &= ~mask;
729
- timer->context.twer &= ~mask;
730668 omap_dm_timer_disable(timer);
731669 return 0;
732670 }
....@@ -735,7 +673,7 @@
735673 {
736674 unsigned int l;
737675
738
- if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
676
+ if (unlikely(!timer || !atomic_read(&timer->enabled))) {
739677 pr_err("%s: timer not available or enabled.\n", __func__);
740678 return 0;
741679 }
....@@ -747,7 +685,7 @@
747685
748686 static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
749687 {
750
- if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
688
+ if (unlikely(!timer || !atomic_read(&timer->enabled)))
751689 return -EINVAL;
752690
753691 __omap_dm_timer_write_status(timer, value);
....@@ -757,7 +695,7 @@
757695
758696 static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
759697 {
760
- if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
698
+ if (unlikely(!timer || !atomic_read(&timer->enabled))) {
761699 pr_err("%s: timer not iavailable or enabled.\n", __func__);
762700 return 0;
763701 }
....@@ -767,7 +705,7 @@
767705
768706 static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
769707 {
770
- if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
708
+ if (unlikely(!timer || !atomic_read(&timer->enabled))) {
771709 pr_err("%s: timer not available or enabled.\n", __func__);
772710 return -EINVAL;
773711 }
....@@ -795,6 +733,37 @@
795733 return 0;
796734 }
797735
736
+static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
737
+{
738
+ struct omap_dm_timer *timer = dev_get_drvdata(dev);
739
+
740
+ atomic_set(&timer->enabled, 0);
741
+
742
+ if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base)
743
+ return 0;
744
+
745
+ omap_timer_save_context(timer);
746
+
747
+ return 0;
748
+}
749
+
750
+static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)
751
+{
752
+ struct omap_dm_timer *timer = dev_get_drvdata(dev);
753
+
754
+ if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base)
755
+ omap_timer_restore_context(timer);
756
+
757
+ atomic_set(&timer->enabled, 1);
758
+
759
+ return 0;
760
+}
761
+
762
+static const struct dev_pm_ops omap_dm_timer_pm_ops = {
763
+ SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend,
764
+ omap_dm_timer_runtime_resume, NULL)
765
+};
766
+
798767 static const struct of_device_id omap_timer_match[];
799768
800769 /**
....@@ -808,7 +777,6 @@
808777 {
809778 unsigned long flags;
810779 struct omap_dm_timer *timer;
811
- struct resource *mem, *irq;
812780 struct device *dev = &pdev->dev;
813781 const struct dmtimer_platform_data *pdata;
814782 int ret;
....@@ -824,26 +792,20 @@
824792 return -ENODEV;
825793 }
826794
827
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
828
- if (unlikely(!irq)) {
829
- dev_err(dev, "%s: no IRQ resource.\n", __func__);
830
- return -ENODEV;
831
- }
832
-
833
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
834
- if (unlikely(!mem)) {
835
- dev_err(dev, "%s: no memory resource.\n", __func__);
836
- return -ENODEV;
837
- }
838
-
839795 timer = devm_kzalloc(dev, sizeof(*timer), GFP_KERNEL);
840796 if (!timer)
841797 return -ENOMEM;
842798
799
+ timer->irq = platform_get_irq(pdev, 0);
800
+ if (timer->irq < 0)
801
+ return timer->irq;
802
+
843803 timer->fclk = ERR_PTR(-ENODEV);
844
- timer->io_base = devm_ioremap_resource(dev, mem);
804
+ timer->io_base = devm_platform_ioremap_resource(pdev, 0);
845805 if (IS_ERR(timer->io_base))
846806 return PTR_ERR(timer->io_base);
807
+
808
+ platform_set_drvdata(pdev, timer);
847809
848810 if (dev->of_node) {
849811 if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
....@@ -858,13 +820,16 @@
858820 timer->id = pdev->id;
859821 timer->capability = pdata->timer_capability;
860822 timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
861
- timer->get_context_loss_count = pdata->get_context_loss_count;
823
+ }
824
+
825
+ if (!(timer->capability & OMAP_TIMER_ALWON)) {
826
+ timer->nb.notifier_call = omap_timer_context_notifier;
827
+ cpu_pm_register_notifier(&timer->nb);
862828 }
863829
864830 if (pdata)
865831 timer->errata = pdata->timer_errata;
866832
867
- timer->irq = irq->start;
868833 timer->pdev = pdev;
869834
870835 pm_runtime_enable(dev);
....@@ -913,6 +878,8 @@
913878 list_for_each_entry(timer, &omap_timer_list, node)
914879 if (!strcmp(dev_name(&timer->pdev->dev),
915880 dev_name(&pdev->dev))) {
881
+ if (!(timer->capability & OMAP_TIMER_ALWON))
882
+ cpu_pm_unregister_notifier(&timer->nb);
916883 list_del(&timer->node);
917884 ret = 0;
918885 break;
....@@ -924,7 +891,7 @@
924891 return ret;
925892 }
926893
927
-const static struct omap_dm_timer_ops dmtimer_ops = {
894
+static const struct omap_dm_timer_ops dmtimer_ops = {
928895 .request_by_node = omap_dm_timer_request_by_node,
929896 .request_specific = omap_dm_timer_request_specific,
930897 .request = omap_dm_timer_request,
....@@ -941,6 +908,7 @@
941908 .set_load = omap_dm_timer_set_load,
942909 .set_match = omap_dm_timer_set_match,
943910 .set_pwm = omap_dm_timer_set_pwm,
911
+ .get_pwm_status = omap_dm_timer_get_pwm_status,
944912 .set_prescaler = omap_dm_timer_set_prescaler,
945913 .read_counter = omap_dm_timer_read_counter,
946914 .write_counter = omap_dm_timer_write_counter,
....@@ -991,13 +959,12 @@
991959 .driver = {
992960 .name = "omap_timer",
993961 .of_match_table = of_match_ptr(omap_timer_match),
962
+ .pm = &omap_dm_timer_pm_ops,
994963 },
995964 };
996965
997
-early_platform_init("earlytimer", &omap_dm_timer_driver);
998966 module_platform_driver(omap_dm_timer_driver);
999967
1000968 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
1001969 MODULE_LICENSE("GPL");
1002
-MODULE_ALIAS("platform:" DRIVER_NAME);
1003970 MODULE_AUTHOR("Texas Instruments Inc");