Commit 5e20931c authored by Tony Lindgren's avatar Tony Lindgren Committed by Daniel Lezcano

clocksource/drivers/timer-ti-dm: Prepare for using cpuidle

Let's add runtime_suspend and resume functions and atomic enabled
flag. This way we can use these when converting to use cpuidle
for saving and restoring device context.

And we need to maintain the driver state in the driver as documented
in "9. Autosuspend, or automatically-delayed suspends" in the
Documentation/power/runtime_pm.rst document related to using driver
private lock and races with runtime_suspend().
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarLokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20200305082715.15861-3-lokeshvutla@ti.com
parent 341e8cba
...@@ -491,7 +491,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) ...@@ -491,7 +491,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
int omap_dm_timer_trigger(struct omap_dm_timer *timer) int omap_dm_timer_trigger(struct omap_dm_timer *timer)
{ {
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not available or enabled.\n", __func__); pr_err("%s: timer not available or enabled.\n", __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -690,7 +690,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) ...@@ -690,7 +690,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
{ {
unsigned int l; unsigned int l;
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not available or enabled.\n", __func__); pr_err("%s: timer not available or enabled.\n", __func__);
return 0; return 0;
} }
...@@ -702,7 +702,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) ...@@ -702,7 +702,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{ {
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) if (unlikely(!timer || !atomic_read(&timer->enabled)))
return -EINVAL; return -EINVAL;
__omap_dm_timer_write_status(timer, value); __omap_dm_timer_write_status(timer, value);
...@@ -712,7 +712,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int ...@@ -712,7 +712,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int
static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{ {
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not iavailable or enabled.\n", __func__); pr_err("%s: timer not iavailable or enabled.\n", __func__);
return 0; return 0;
} }
...@@ -722,7 +722,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) ...@@ -722,7 +722,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
{ {
if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) {
pr_err("%s: timer not available or enabled.\n", __func__); pr_err("%s: timer not available or enabled.\n", __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -750,6 +750,29 @@ int omap_dm_timers_active(void) ...@@ -750,6 +750,29 @@ int omap_dm_timers_active(void)
return 0; return 0;
} }
static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
{
struct omap_dm_timer *timer = dev_get_drvdata(dev);
atomic_set(&timer->enabled, 0);
return 0;
}
static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)
{
struct omap_dm_timer *timer = dev_get_drvdata(dev);
atomic_set(&timer->enabled, 1);
return 0;
}
static const struct dev_pm_ops omap_dm_timer_pm_ops = {
SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend,
omap_dm_timer_runtime_resume, NULL)
};
static const struct of_device_id omap_timer_match[]; static const struct of_device_id omap_timer_match[];
/** /**
...@@ -791,6 +814,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev) ...@@ -791,6 +814,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
if (IS_ERR(timer->io_base)) if (IS_ERR(timer->io_base))
return PTR_ERR(timer->io_base); return PTR_ERR(timer->io_base);
platform_set_drvdata(pdev, timer);
if (dev->of_node) { if (dev->of_node) {
if (of_find_property(dev->of_node, "ti,timer-alwon", NULL)) if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
timer->capability |= OMAP_TIMER_ALWON; timer->capability |= OMAP_TIMER_ALWON;
...@@ -936,6 +961,7 @@ static struct platform_driver omap_dm_timer_driver = { ...@@ -936,6 +961,7 @@ static struct platform_driver omap_dm_timer_driver = {
.driver = { .driver = {
.name = "omap_timer", .name = "omap_timer",
.of_match_table = of_match_ptr(omap_timer_match), .of_match_table = of_match_ptr(omap_timer_match),
.pm = &omap_dm_timer_pm_ops,
}, },
}; };
......
...@@ -105,6 +105,7 @@ struct omap_dm_timer { ...@@ -105,6 +105,7 @@ struct omap_dm_timer {
void __iomem *pend; /* write pending */ void __iomem *pend; /* write pending */
void __iomem *func_base; /* function register base */ void __iomem *func_base; /* function register base */
atomic_t enabled;
unsigned long rate; unsigned long rate;
unsigned reserved:1; unsigned reserved:1;
unsigned posted:1; unsigned posted:1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment