Skip to content

Commit f7867cf

Browse files
committed
Merge branch 'timers/drivers/timer-ti-dm' into timers/drivers/next
2 parents 0585244 + 02e6d54 commit f7867cf

File tree

4 files changed

+119
-82
lines changed

4 files changed

+119
-82
lines changed

drivers/clocksource/timer-ti-dm.c

Lines changed: 109 additions & 74 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 <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>
@@ -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;
@@ -196,21 +221,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
196221

197222
static void omap_dm_timer_enable(struct omap_dm_timer *timer)
198223
{
199-
int c;
200-
201224
pm_runtime_get_sync(&timer->pdev->dev);
202-
203-
if (!(timer->capability & OMAP_TIMER_ALWON)) {
204-
if (timer->get_context_loss_count) {
205-
c = timer->get_context_loss_count(&timer->pdev->dev);
206-
if (c != timer->ctx_loss_count) {
207-
omap_timer_restore_context(timer);
208-
timer->ctx_loss_count = c;
209-
}
210-
} else {
211-
omap_timer_restore_context(timer);
212-
}
213-
}
214225
}
215226

216227
static void omap_dm_timer_disable(struct omap_dm_timer *timer)
@@ -477,7 +488,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
477488

478489
int omap_dm_timer_trigger(struct omap_dm_timer *timer)
479490
{
480-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
491+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
481492
pr_err("%s: timer not available or enabled.\n", __func__);
482493
return -EINVAL;
483494
}
@@ -501,8 +512,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
501512
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
502513
}
503514

504-
/* Save the context */
505-
timer->context.tclr = l;
506515
return 0;
507516
}
508517

@@ -518,37 +527,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
518527

519528
__omap_dm_timer_stop(timer, timer->posted, rate);
520529

521-
/*
522-
* Since the register values are computed and written within
523-
* __omap_dm_timer_stop, we need to use read to retrieve the
524-
* context.
525-
*/
526-
timer->context.tclr =
527-
omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
528530
omap_dm_timer_disable(timer);
529531
return 0;
530532
}
531533

532-
static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
534+
static int omap_dm_timer_set_load(struct omap_dm_timer *timer,
533535
unsigned int load)
534536
{
535-
u32 l;
536-
537537
if (unlikely(!timer))
538538
return -EINVAL;
539539

540540
omap_dm_timer_enable(timer);
541-
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
542-
if (autoreload)
543-
l |= OMAP_TIMER_CTRL_AR;
544-
else
545-
l &= ~OMAP_TIMER_CTRL_AR;
546-
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
547541
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
548542

549-
/* Save the context */
550-
timer->context.tclr = l;
551-
timer->context.tldr = load;
552543
omap_dm_timer_disable(timer);
553544
return 0;
554545
}
@@ -570,15 +561,12 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
570561
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
571562
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
572563

573-
/* Save the context */
574-
timer->context.tclr = l;
575-
timer->context.tmar = match;
576564
omap_dm_timer_disable(timer);
577565
return 0;
578566
}
579567

580568
static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
581-
int toggle, int trigger)
569+
int toggle, int trigger, int autoreload)
582570
{
583571
u32 l;
584572

@@ -588,20 +576,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
588576
omap_dm_timer_enable(timer);
589577
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
590578
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
591-
OMAP_TIMER_CTRL_PT | (0x03 << 10));
579+
OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR);
592580
if (def_on)
593581
l |= OMAP_TIMER_CTRL_SCPWM;
594582
if (toggle)
595583
l |= OMAP_TIMER_CTRL_PT;
596584
l |= trigger << 10;
585+
if (autoreload)
586+
l |= OMAP_TIMER_CTRL_AR;
597587
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
598588

599-
/* Save the context */
600-
timer->context.tclr = l;
601589
omap_dm_timer_disable(timer);
602590
return 0;
603591
}
604592

593+
static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer)
594+
{
595+
u32 l;
596+
597+
if (unlikely(!timer))
598+
return -EINVAL;
599+
600+
omap_dm_timer_enable(timer);
601+
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
602+
omap_dm_timer_disable(timer);
603+
604+
return l;
605+
}
606+
605607
static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
606608
int prescaler)
607609
{
@@ -619,8 +621,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
619621
}
620622
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
621623

622-
/* Save the context */
623-
timer->context.tclr = l;
624624
omap_dm_timer_disable(timer);
625625
return 0;
626626
}
@@ -634,9 +634,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
634634
omap_dm_timer_enable(timer);
635635
__omap_dm_timer_int_enable(timer, value);
636636

637-
/* Save the context */
638-
timer->context.tier = value;
639-
timer->context.twer = value;
640637
omap_dm_timer_disable(timer);
641638
return 0;
642639
}
@@ -664,9 +661,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
664661
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
665662
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
666663

667-
/* Save the context */
668-
timer->context.tier &= ~mask;
669-
timer->context.twer &= ~mask;
670664
omap_dm_timer_disable(timer);
671665
return 0;
672666
}
@@ -675,7 +669,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
675669
{
676670
unsigned int l;
677671

678-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
672+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
679673
pr_err("%s: timer not available or enabled.\n", __func__);
680674
return 0;
681675
}
@@ -687,7 +681,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
687681

688682
static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
689683
{
690-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
684+
if (unlikely(!timer || !atomic_read(&timer->enabled)))
691685
return -EINVAL;
692686

693687
__omap_dm_timer_write_status(timer, value);
@@ -697,7 +691,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int
697691

698692
static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
699693
{
700-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
694+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
701695
pr_err("%s: timer not iavailable or enabled.\n", __func__);
702696
return 0;
703697
}
@@ -707,7 +701,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
707701

708702
static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
709703
{
710-
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
704+
if (unlikely(!timer || !atomic_read(&timer->enabled))) {
711705
pr_err("%s: timer not available or enabled.\n", __func__);
712706
return -EINVAL;
713707
}
@@ -735,6 +729,37 @@ int omap_dm_timers_active(void)
735729
return 0;
736730
}
737731

732+
static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
733+
{
734+
struct omap_dm_timer *timer = dev_get_drvdata(dev);
735+
736+
atomic_set(&timer->enabled, 0);
737+
738+
if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base)
739+
return 0;
740+
741+
omap_timer_save_context(timer);
742+
743+
return 0;
744+
}
745+
746+
static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)
747+
{
748+
struct omap_dm_timer *timer = dev_get_drvdata(dev);
749+
750+
if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base)
751+
omap_timer_restore_context(timer);
752+
753+
atomic_set(&timer->enabled, 1);
754+
755+
return 0;
756+
}
757+
758+
static const struct dev_pm_ops omap_dm_timer_pm_ops = {
759+
SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend,
760+
omap_dm_timer_runtime_resume, NULL)
761+
};
762+
738763
static const struct of_device_id omap_timer_match[];
739764

740765
/**
@@ -776,6 +801,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
776801
if (IS_ERR(timer->io_base))
777802
return PTR_ERR(timer->io_base);
778803

804+
platform_set_drvdata(pdev, timer);
805+
779806
if (dev->of_node) {
780807
if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
781808
timer->capability |= OMAP_TIMER_ALWON;
@@ -789,7 +816,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
789816
timer->id = pdev->id;
790817
timer->capability = pdata->timer_capability;
791818
timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
792-
timer->get_context_loss_count = pdata->get_context_loss_count;
819+
}
820+
821+
if (!(timer->capability & OMAP_TIMER_ALWON)) {
822+
timer->nb.notifier_call = omap_timer_context_notifier;
823+
cpu_pm_register_notifier(&timer->nb);
793824
}
794825

795826
if (pdata)
@@ -843,6 +874,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
843874
list_for_each_entry(timer, &omap_timer_list, node)
844875
if (!strcmp(dev_name(&timer->pdev->dev),
845876
dev_name(&pdev->dev))) {
877+
if (!(timer->capability & OMAP_TIMER_ALWON))
878+
cpu_pm_unregister_notifier(&timer->nb);
846879
list_del(&timer->node);
847880
ret = 0;
848881
break;
@@ -871,6 +904,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = {
871904
.set_load = omap_dm_timer_set_load,
872905
.set_match = omap_dm_timer_set_match,
873906
.set_pwm = omap_dm_timer_set_pwm,
907+
.get_pwm_status = omap_dm_timer_get_pwm_status,
874908
.set_prescaler = omap_dm_timer_set_prescaler,
875909
.read_counter = omap_dm_timer_read_counter,
876910
.write_counter = omap_dm_timer_write_counter,
@@ -921,6 +955,7 @@ static struct platform_driver omap_dm_timer_driver = {
921955
.driver = {
922956
.name = "omap_timer",
923957
.of_match_table = of_match_ptr(omap_timer_match),
958+
.pm = &omap_dm_timer_pm_ops,
924959
},
925960
};
926961

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)