Skip to content

Commit 74c8249

Browse files
committed
Merge branch 'timers/drivers/timer-ti-dm' of https://git.linaro.org/people/dlezcano/linux into for-next
2 parents bb6d3fb + 02e6d54 commit 74c8249

File tree

4 files changed

+119
-83
lines changed

4 files changed

+119
-83
lines changed

drivers/clocksource/timer-ti-dm.c

Lines changed: 109 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// SPDX-License-Identifier: GPL-2.0+
12
/*
23
* linux/arch/arm/plat-omap/dmtimer.c
34
*
@@ -15,28 +16,11 @@
1516
*
1617
* Copyright (C) 2009 Texas Instruments
1718
* 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.
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>
@@ -109,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
10993
timer->context.tclr);
11094
}
11195

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+
112137
static int omap_dm_timer_reset(struct omap_dm_timer *timer)
113138
{
114139
u32 l, timeout = 100000;
@@ -225,21 +250,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
225250

226251
static void omap_dm_timer_enable(struct omap_dm_timer *timer)
227252
{
228-
int c;
229-
230253
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-
}
243254
}
244255

245256
static void omap_dm_timer_disable(struct omap_dm_timer *timer)
@@ -508,7 +519,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
508519

509520
int omap_dm_timer_trigger(struct omap_dm_timer *timer)
510521
{
511-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
522+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
512523
pr_err("%s: timer not available or enabled.\n", __func__);
513524
return -EINVAL;
514525
}
@@ -532,8 +543,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
532543
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
533544
}
534545

535-
/* Save the context */
536-
timer->context.tclr = l;
537546
return 0;
538547
}
539548

@@ -549,38 +558,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
549558

550559
__omap_dm_timer_stop(timer, timer->posted, rate);
551560

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);
559561
omap_dm_timer_disable(timer);
560562
return 0;
561563
}
562564

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,
564566
unsigned int load)
565567
{
566-
u32 l;
567-
568568
if (unlikely(!timer))
569569
return -EINVAL;
570570

571571
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);
578572
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
579573

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;
584574
omap_dm_timer_disable(timer);
585575
return 0;
586576
}
@@ -602,15 +592,12 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
602592
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
603593
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
604594

605-
/* Save the context */
606-
timer->context.tclr = l;
607-
timer->context.tmar = match;
608595
omap_dm_timer_disable(timer);
609596
return 0;
610597
}
611598

612599
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)
614601
{
615602
u32 l;
616603

@@ -620,20 +607,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
620607
omap_dm_timer_enable(timer);
621608
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
622609
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);
624611
if (def_on)
625612
l |= OMAP_TIMER_CTRL_SCPWM;
626613
if (toggle)
627614
l |= OMAP_TIMER_CTRL_PT;
628615
l |= trigger << 10;
616+
if (autoreload)
617+
l |= OMAP_TIMER_CTRL_AR;
629618
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
630619

631-
/* Save the context */
632-
timer->context.tclr = l;
633620
omap_dm_timer_disable(timer);
634621
return 0;
635622
}
636623

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+
637638
static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
638639
int prescaler)
639640
{
@@ -651,8 +652,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
651652
}
652653
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
653654

654-
/* Save the context */
655-
timer->context.tclr = l;
656655
omap_dm_timer_disable(timer);
657656
return 0;
658657
}
@@ -666,9 +665,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
666665
omap_dm_timer_enable(timer);
667666
__omap_dm_timer_int_enable(timer, value);
668667

669-
/* Save the context */
670-
timer->context.tier = value;
671-
timer->context.twer = value;
672668
omap_dm_timer_disable(timer);
673669
return 0;
674670
}
@@ -696,9 +692,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
696692
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
697693
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
698694

699-
/* Save the context */
700-
timer->context.tier &= ~mask;
701-
timer->context.twer &= ~mask;
702695
omap_dm_timer_disable(timer);
703696
return 0;
704697
}
@@ -707,7 +700,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
707700
{
708701
unsigned int l;
709702

710-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
703+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
711704
pr_err("%s: timer not available or enabled.\n", __func__);
712705
return 0;
713706
}
@@ -719,7 +712,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
719712

720713
static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
721714
{
722-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
715+
if (unlikely(!timer || !atomic_read(&timer->enabled)))
723716
return -EINVAL;
724717

725718
__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
729722

730723
static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
731724
{
732-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
725+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
733726
pr_err("%s: timer not iavailable or enabled.\n", __func__);
734727
return 0;
735728
}
@@ -739,7 +732,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
739732

740733
static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
741734
{
742-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
735+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
743736
pr_err("%s: timer not available or enabled.\n", __func__);
744737
return -EINVAL;
745738
}
@@ -767,6 +760,37 @@ int omap_dm_timers_active(void)
767760
return 0;
768761
}
769762

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+
770794
static const struct of_device_id omap_timer_match[];
771795

772796
/**
@@ -808,6 +832,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
808832
if (IS_ERR(timer->io_base))
809833
return PTR_ERR(timer->io_base);
810834

835+
platform_set_drvdata(pdev, timer);
836+
811837
if (dev->of_node) {
812838
if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
813839
timer->capability |= OMAP_TIMER_ALWON;
@@ -821,7 +847,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
821847
timer->id = pdev->id;
822848
timer->capability = pdata->timer_capability;
823849
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);
825855
}
826856

827857
if (pdata)
@@ -875,6 +905,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
875905
list_for_each_entry(timer, &omap_timer_list, node)
876906
if (!strcmp(dev_name(&timer->pdev->dev),
877907
dev_name(&pdev->dev))) {
908+
if (!(timer->capability & OMAP_TIMER_ALWON))
909+
cpu_pm_unregister_notifier(&timer->nb);
878910
list_del(&timer->node);
879911
ret = 0;
880912
break;
@@ -903,6 +935,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = {
903935
.set_load = omap_dm_timer_set_load,
904936
.set_match = omap_dm_timer_set_match,
905937
.set_pwm = omap_dm_timer_set_pwm,
938+
.get_pwm_status = omap_dm_timer_get_pwm_status,
906939
.set_prescaler = omap_dm_timer_set_prescaler,
907940
.read_counter = omap_dm_timer_read_counter,
908941
.write_counter = omap_dm_timer_write_counter,
@@ -953,6 +986,7 @@ static struct platform_driver omap_dm_timer_driver = {
953986
.driver = {
954987
.name = "omap_timer",
955988
.of_match_table = of_match_ptr(omap_timer_match),
989+
.pm = &omap_dm_timer_pm_ops,
956990
},
957991
};
958992

drivers/pwm/pwm-omap-dmtimer.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
183183
if (timer_active)
184184
omap->pdata->stop(omap->dm_timer);
185185

186-
omap->pdata->set_load(omap->dm_timer, true, load_value);
186+
omap->pdata->set_load(omap->dm_timer, load_value);
187187
omap->pdata->set_match(omap->dm_timer, true, match_value);
188188

189189
dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n",
@@ -192,7 +192,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
192192
omap->pdata->set_pwm(omap->dm_timer,
193193
pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED,
194194
true,
195-
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
195+
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE,
196+
true);
196197

197198
/* If config was called while timer was running it must be reenabled. */
198199
if (timer_active)
@@ -222,7 +223,8 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,
222223
omap->pdata->set_pwm(omap->dm_timer,
223224
polarity == PWM_POLARITY_INVERSED,
224225
true,
225-
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
226+
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE,
227+
true);
226228
mutex_unlock(&omap->mutex);
227229

228230
return 0;

0 commit comments

Comments
 (0)