linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates
@ 2020-03-05  8:27 Lokesh Vutla
  2020-03-05  8:27 ` [PATCH v3 1/6] clocksource: timer-ti-dm: Convert to SPDX identifier Lokesh Vutla
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla

This series fixes dm_timer_ops used for enabling the pwm and enables
cpu_pm notifier for context save and restore. This acts as a preparatory
series for enabling dynamic period updates for pwm omap dm timer driver.

Changes since v2:
- Incorporated changes from Tony

Changes since v1:
- Updated License header to use SPDX identifier
- Implemented cpu_pm notfier
- Added support for getting pwm current status
- Extended set_pwm functionality.

Lokesh Vutla (5):
  clocksource: timer-ti-dm: Convert to SPDX identifier
  clocksource: timer-ti-dm: Implement cpu_pm notifier for context save
    and restore
  clocksource: timer-ti-dm: Do not update counter on updating the period
  clocksource: timer-ti-dm: Add support to get pwm current status
  clocksource: timer-ti-dm: Enable autoreload in set_pwm

Tony Lindgren (1):
  clocksource: timer-ti-dm: Prepare for using cpuidle

 drivers/clocksource/timer-ti-dm.c          | 186 ++++++++++++---------
 drivers/pwm/pwm-omap-dmtimer.c             |   8 +-
 include/clocksource/timer-ti-dm.h          |   4 +-
 include/linux/platform_data/dmtimer-omap.h |   6 +-
 4 files changed, 121 insertions(+), 83 deletions(-)

-- 
2.23.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v3 1/6] clocksource: timer-ti-dm: Convert to SPDX identifier
  2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
@ 2020-03-05  8:27 ` Lokesh Vutla
  2020-03-06 16:57   ` Tony Lindgren
  2020-03-05  8:27 ` [PATCH v3 2/6] clocksource: timer-ti-dm: Prepare for using cpuidle Lokesh Vutla
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla

Use SPDX-License-Identifier instead of a verbose license text.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 drivers/clocksource/timer-ti-dm.c | 19 +------------------
 1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index d8637a60a7eb..bf132d321ecc 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * linux/arch/arm/plat-omap/dmtimer.c
  *
@@ -15,24 +16,6 @@
  *
  * Copyright (C) 2009 Texas Instruments
  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/clk.h>
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 2/6] clocksource: timer-ti-dm: Prepare for using cpuidle
  2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
  2020-03-05  8:27 ` [PATCH v3 1/6] clocksource: timer-ti-dm: Convert to SPDX identifier Lokesh Vutla
@ 2020-03-05  8:27 ` Lokesh Vutla
  2020-03-05  8:27 ` [PATCH v3 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore Lokesh Vutla
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla, Tony Lindgren

From: Tony Lindgren <tony@atomide.com>

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: Tony Lindgren <tony@atomide.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 drivers/clocksource/timer-ti-dm.c | 36 ++++++++++++++++++++++++++-----
 include/clocksource/timer-ti-dm.h |  1 +
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index bf132d321ecc..dae91969018d 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -460,7 +460,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 
 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__);
 		return -EINVAL;
 	}
@@ -659,7 +659,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
 	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__);
 		return 0;
 	}
@@ -671,7 +671,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)
 {
-	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
+	if (unlikely(!timer || !atomic_read(&timer->enabled)))
 		return -EINVAL;
 
 	__omap_dm_timer_write_status(timer, value);
@@ -681,7 +681,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)
 {
-	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__);
 		return 0;
 	}
@@ -691,7 +691,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)
 {
-	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__);
 		return -EINVAL;
 	}
@@ -719,6 +719,29 @@ int omap_dm_timers_active(void)
 	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[];
 
 /**
@@ -760,6 +783,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
 	if (IS_ERR(timer->io_base))
 		return PTR_ERR(timer->io_base);
 
+	platform_set_drvdata(pdev, timer);
+
 	if (dev->of_node) {
 		if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
 			timer->capability |= OMAP_TIMER_ALWON;
@@ -905,6 +930,7 @@ static struct platform_driver omap_dm_timer_driver = {
 	.driver = {
 		.name   = "omap_timer",
 		.of_match_table = of_match_ptr(omap_timer_match),
+		.pm = &omap_dm_timer_pm_ops,
 	},
 };
 
diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h
index 7d9598dc578d..eef5de300731 100644
--- a/include/clocksource/timer-ti-dm.h
+++ b/include/clocksource/timer-ti-dm.h
@@ -105,6 +105,7 @@ struct omap_dm_timer {
 	void __iomem	*pend;		/* write pending */
 	void __iomem	*func_base;	/* function register base */
 
+	atomic_t enabled;
 	unsigned long rate;
 	unsigned reserved:1;
 	unsigned posted:1;
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore
  2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
  2020-03-05  8:27 ` [PATCH v3 1/6] clocksource: timer-ti-dm: Convert to SPDX identifier Lokesh Vutla
  2020-03-05  8:27 ` [PATCH v3 2/6] clocksource: timer-ti-dm: Prepare for using cpuidle Lokesh Vutla
@ 2020-03-05  8:27 ` Lokesh Vutla
  2020-03-16 10:51   ` Daniel Lezcano
  2020-03-16 11:14   ` [PATCH v4 " Lokesh Vutla
  2020-03-05  8:27 ` [PATCH v3 4/6] clocksource: timer-ti-dm: Do not update counter on updating the period Lokesh Vutla
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla, Tony Lindgren

omap_dm_timer_enable() restores the entire context(including counter)
based on 2 conditions:
- If get_context_loss_count is populated and context is lost.
- If get_context_loss_count is not populated update unconditionally.

Case2 has a side effect of updating the counter register even though
context is not lost. When timer is configured in pwm mode, this is
causing undesired behaviour in the pwm period.

Instead of using get_context_loss_count call back, implement cpu_pm
notifier with context save and restore support. And delete the
get_context_loss_count callback all together.

Suggested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[tony@atomide.com: removed pm_runtime calls from cpuidle calls]
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/clocksource/timer-ti-dm.c | 99 ++++++++++++++++++-------------
 include/clocksource/timer-ti-dm.h |  3 +-
 2 files changed, 60 insertions(+), 42 deletions(-)

diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index dae91969018d..e6b6123ec567 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -20,6 +20,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/cpu_pm.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/device.h>
@@ -92,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
 				timer->context.tclr);
 }
 
+static void omap_timer_save_context(struct omap_dm_timer *timer)
+{
+	timer->context.tclr =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	timer->context.twer =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG);
+	timer->context.tldr =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG);
+	timer->context.tmar =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG);
+	timer->context.tier = readl_relaxed(timer->irq_ena);
+	timer->context.tsicr =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG);
+}
+
+static int omap_timer_context_notifier(struct notifier_block *nb,
+				       unsigned long cmd, void *v)
+{
+	struct omap_dm_timer *timer;
+
+	timer = container_of(nb, struct omap_dm_timer, nb);
+
+	switch (cmd) {
+	case CPU_CLUSTER_PM_ENTER:
+		if ((timer->capability & OMAP_TIMER_ALWON) ||
+		    !atomic_read(&timer->enabled))
+			break;
+		omap_timer_save_context(timer);
+		break;
+	case CPU_CLUSTER_PM_ENTER_FAILED:
+	case CPU_CLUSTER_PM_EXIT:
+		if ((timer->capability & OMAP_TIMER_ALWON) ||
+		    !atomic_read(&timer->enabled))
+			break;
+		omap_timer_restore_context(timer);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
 static int omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
 	u32 l, timeout = 100000;
@@ -179,21 +221,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 
 static void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
-	int c;
-
 	pm_runtime_get_sync(&timer->pdev->dev);
-
-	if (!(timer->capability & OMAP_TIMER_ALWON)) {
-		if (timer->get_context_loss_count) {
-			c = timer->get_context_loss_count(&timer->pdev->dev);
-			if (c != timer->ctx_loss_count) {
-				omap_timer_restore_context(timer);
-				timer->ctx_loss_count = c;
-			}
-		} else {
-			omap_timer_restore_context(timer);
-		}
-	}
 }
 
 static void omap_dm_timer_disable(struct omap_dm_timer *timer)
@@ -484,8 +512,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	}
 
-	/* Save the context */
-	timer->context.tclr = l;
 	return 0;
 }
 
@@ -501,13 +527,6 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
 
 	__omap_dm_timer_stop(timer, timer->posted, rate);
 
-	/*
-	 * Since the register values are computed and written within
-	 * __omap_dm_timer_stop, we need to use read to retrieve the
-	 * context.
-	 */
-	timer->context.tclr =
-			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -530,9 +549,6 @@ static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
-	/* Save the context */
-	timer->context.tclr = l;
-	timer->context.tldr = load;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -554,9 +570,6 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
-	/* Save the context */
-	timer->context.tclr = l;
-	timer->context.tmar = match;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -580,8 +593,6 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 	l |= trigger << 10;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
-	/* Save the context */
-	timer->context.tclr = l;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -603,8 +614,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
 	}
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
-	/* Save the context */
-	timer->context.tclr = l;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -618,9 +627,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 	omap_dm_timer_enable(timer);
 	__omap_dm_timer_int_enable(timer, value);
 
-	/* Save the context */
-	timer->context.tier = value;
-	timer->context.twer = value;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -648,9 +654,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
 
-	/* Save the context */
-	timer->context.tier &= ~mask;
-	timer->context.twer &= ~mask;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -725,6 +728,12 @@ static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
 
 	atomic_set(&timer->enabled, 0);
 
+	if (timer->capability & OMAP_TIMER_ALWON ||
+	    !timer->func_base)
+	    return 0;
+
+	omap_timer_save_context(timer);
+
 	return 0;
 }
 
@@ -732,6 +741,10 @@ static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)
 {
 	struct omap_dm_timer *timer = dev_get_drvdata(dev);
 
+	if (!(timer->capability & OMAP_TIMER_ALWON) &&
+	    timer->func_base)
+		omap_timer_restore_context(timer);
+
 	atomic_set(&timer->enabled, 1);
 
 	return 0;
@@ -798,7 +811,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
 		timer->id = pdev->id;
 		timer->capability = pdata->timer_capability;
 		timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
-		timer->get_context_loss_count = pdata->get_context_loss_count;
+	}
+
+	if (!(timer->capability & OMAP_TIMER_ALWON)) {
+		timer->nb.notifier_call = omap_timer_context_notifier;
+		cpu_pm_register_notifier(&timer->nb);
 	}
 
 	if (pdata)
@@ -852,6 +869,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
 	list_for_each_entry(timer, &omap_timer_list, node)
 		if (!strcmp(dev_name(&timer->pdev->dev),
 			    dev_name(&pdev->dev))) {
+			if (!(timer->capability & OMAP_TIMER_ALWON))
+				cpu_pm_unregister_notifier(&timer->nb);
 			list_del(&timer->node);
 			ret = 0;
 			break;
diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h
index eef5de300731..25f05235866e 100644
--- a/include/clocksource/timer-ti-dm.h
+++ b/include/clocksource/timer-ti-dm.h
@@ -110,13 +110,12 @@ struct omap_dm_timer {
 	unsigned reserved:1;
 	unsigned posted:1;
 	struct timer_regs context;
-	int (*get_context_loss_count)(struct device *);
-	int ctx_loss_count;
 	int revision;
 	u32 capability;
 	u32 errata;
 	struct platform_device *pdev;
 	struct list_head node;
+	struct notifier_block nb;
 };
 
 int omap_dm_timer_reserve_systimer(int id);
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 4/6] clocksource: timer-ti-dm: Do not update counter on updating the period
  2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
                   ` (2 preceding siblings ...)
  2020-03-05  8:27 ` [PATCH v3 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore Lokesh Vutla
@ 2020-03-05  8:27 ` Lokesh Vutla
  2020-03-05  8:27 ` [PATCH v3 5/6] clocksource: timer-ti-dm: Add support to get pwm current status Lokesh Vutla
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla, Tony Lindgren

Write to trigger register(OMAP_TIMER_TRIGGER_REG) will load the value
in Load register(OMAP_TIMER_LOAD_REG) into Counter register
(OMAP_TIMER_COUNTER_REG).

omap_dm_timer_set_load() writes into trigger register every time load
register is updated. When timer is configured in pwm mode, this causes
disruption in current pwm cycle, which is not expected especially when
pwm is used as PPS signal for synchronized PTP clocks. So do not write
into trigger register on updating the period.

Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 drivers/clocksource/timer-ti-dm.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index e6b6123ec567..8f6d477d2078 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -548,7 +548,6 @@ static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
 	omap_dm_timer_disable(timer);
 	return 0;
 }
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 5/6] clocksource: timer-ti-dm: Add support to get pwm current status
  2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
                   ` (3 preceding siblings ...)
  2020-03-05  8:27 ` [PATCH v3 4/6] clocksource: timer-ti-dm: Do not update counter on updating the period Lokesh Vutla
@ 2020-03-05  8:27 ` Lokesh Vutla
  2020-03-06 17:08   ` Tony Lindgren
  2020-03-05  8:27 ` [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm Lokesh Vutla
  2020-03-06 17:19 ` [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Tony Lindgren
  6 siblings, 1 reply; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla

omap_dm_timer_ops provide support to configure the pwm but there is no
support to get the current status. For configuring pwm it is advised to
check the current hw status instead of relying on pwm framework. So
implement a new timer ops to get the current status of pwm.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 drivers/clocksource/timer-ti-dm.c          | 15 +++++++++++++++
 include/linux/platform_data/dmtimer-omap.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index 8f6d477d2078..10e1d08bfc4c 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -596,6 +596,20 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 	return 0;
 }
 
+static int omap_dm_timer_get_pwm_status(struct omap_dm_timer *timer)
+{
+	u32 l;
+
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	omap_dm_timer_disable(timer);
+
+	return l;
+}
+
 static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
 					int prescaler)
 {
@@ -898,6 +912,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = {
 	.set_load = omap_dm_timer_set_load,
 	.set_match = omap_dm_timer_set_match,
 	.set_pwm = omap_dm_timer_set_pwm,
+	.get_pwm_status = omap_dm_timer_get_pwm_status,
 	.set_prescaler = omap_dm_timer_set_prescaler,
 	.read_counter = omap_dm_timer_read_counter,
 	.write_counter = omap_dm_timer_write_counter,
diff --git a/include/linux/platform_data/dmtimer-omap.h b/include/linux/platform_data/dmtimer-omap.h
index bdaaf537604a..3173b7b6ff6f 100644
--- a/include/linux/platform_data/dmtimer-omap.h
+++ b/include/linux/platform_data/dmtimer-omap.h
@@ -36,6 +36,7 @@ struct omap_dm_timer_ops {
 			     unsigned int match);
 	int	(*set_pwm)(struct omap_dm_timer *timer, int def_on,
 			   int toggle, int trigger);
+	int	(*get_pwm_status)(struct omap_dm_timer *timer);
 	int	(*set_prescaler)(struct omap_dm_timer *timer, int prescaler);
 
 	unsigned int (*read_counter)(struct omap_dm_timer *timer);
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm
  2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
                   ` (4 preceding siblings ...)
  2020-03-05  8:27 ` [PATCH v3 5/6] clocksource: timer-ti-dm: Add support to get pwm current status Lokesh Vutla
@ 2020-03-05  8:27 ` Lokesh Vutla
  2020-03-06 17:18   ` Tony Lindgren
  2020-03-30 13:18   ` Thierry Reding
  2020-03-06 17:19 ` [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Tony Lindgren
  6 siblings, 2 replies; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-05  8:27 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla

dm timer ops set_load() api allows to configure the load value and to
set the auto reload feature. But auto reload feature is independent of
load value and should be part of configuring pwm. This way pwm can be
disabled by disabling auto reload feature using set_pwm() so that the
current pwm cycle will be completed. Else pwm disabling causes the
cycle to be stopped abruptly.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 drivers/clocksource/timer-ti-dm.c          | 16 +++++-----------
 drivers/pwm/pwm-omap-dmtimer.c             |  8 +++++---
 include/linux/platform_data/dmtimer-omap.h |  5 ++---
 3 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index 10e1d08bfc4c..1f210ef60b22 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -531,21 +531,13 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
 	return 0;
 }
 
-static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+static int omap_dm_timer_set_load(struct omap_dm_timer *timer,
 				  unsigned int load)
 {
-	u32 l;
-
 	if (unlikely(!timer))
 		return -EINVAL;
 
 	omap_dm_timer_enable(timer);
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	if (autoreload)
-		l |= OMAP_TIMER_CTRL_AR;
-	else
-		l &= ~OMAP_TIMER_CTRL_AR;
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
 	omap_dm_timer_disable(timer);
@@ -574,7 +566,7 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 }
 
 static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
-				 int toggle, int trigger)
+				 int toggle, int trigger, int autoreload)
 {
 	u32 l;
 
@@ -584,12 +576,14 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
-	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
+	       OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR);
 	if (def_on)
 		l |= OMAP_TIMER_CTRL_SCPWM;
 	if (toggle)
 		l |= OMAP_TIMER_CTRL_PT;
 	l |= trigger << 10;
+	if (autoreload)
+		l |= OMAP_TIMER_CTRL_AR;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
 	omap_dm_timer_disable(timer);
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index 88a3c5690fea..9e4378dc6897 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -183,7 +183,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
 	if (timer_active)
 		omap->pdata->stop(omap->dm_timer);
 
-	omap->pdata->set_load(omap->dm_timer, true, load_value);
+	omap->pdata->set_load(omap->dm_timer, load_value);
 	omap->pdata->set_match(omap->dm_timer, true, match_value);
 
 	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,
 	omap->pdata->set_pwm(omap->dm_timer,
 			      pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED,
 			      true,
-			      PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+			      PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE,
+			      true);
 
 	/* If config was called while timer was running it must be reenabled. */
 	if (timer_active)
@@ -222,7 +223,8 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,
 	omap->pdata->set_pwm(omap->dm_timer,
 			      polarity == PWM_POLARITY_INVERSED,
 			      true,
-			      PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+			      PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE,
+			      true);
 	mutex_unlock(&omap->mutex);
 
 	return 0;
diff --git a/include/linux/platform_data/dmtimer-omap.h b/include/linux/platform_data/dmtimer-omap.h
index 3173b7b6ff6f..95d852aef130 100644
--- a/include/linux/platform_data/dmtimer-omap.h
+++ b/include/linux/platform_data/dmtimer-omap.h
@@ -30,12 +30,11 @@ struct omap_dm_timer_ops {
 	int	(*stop)(struct omap_dm_timer *timer);
 	int	(*set_source)(struct omap_dm_timer *timer, int source);
 
-	int	(*set_load)(struct omap_dm_timer *timer, int autoreload,
-			    unsigned int value);
+	int	(*set_load)(struct omap_dm_timer *timer, unsigned int value);
 	int	(*set_match)(struct omap_dm_timer *timer, int enable,
 			     unsigned int match);
 	int	(*set_pwm)(struct omap_dm_timer *timer, int def_on,
-			   int toggle, int trigger);
+			   int toggle, int trigger, int autoreload);
 	int	(*get_pwm_status)(struct omap_dm_timer *timer);
 	int	(*set_prescaler)(struct omap_dm_timer *timer, int prescaler);
 
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 1/6] clocksource: timer-ti-dm: Convert to SPDX identifier
  2020-03-05  8:27 ` [PATCH v3 1/6] clocksource: timer-ti-dm: Convert to SPDX identifier Lokesh Vutla
@ 2020-03-06 16:57   ` Tony Lindgren
  0 siblings, 0 replies; 17+ messages in thread
From: Tony Lindgren @ 2020-03-06 16:57 UTC (permalink / raw)
  To: Lokesh Vutla
  Cc: Daniel Lezcano, Thomas Gleixner, Linux OMAP Mailing List,
	linux-kernel, Thierry Reding, Uwe Kleine-König, linux-pwm,
	Sekhar Nori, Tero Kristo

* Lokesh Vutla <lokeshvutla@ti.com> [200305 08:29]:
> Use SPDX-License-Identifier instead of a verbose license text.

Acked-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 5/6] clocksource: timer-ti-dm: Add support to get pwm current status
  2020-03-05  8:27 ` [PATCH v3 5/6] clocksource: timer-ti-dm: Add support to get pwm current status Lokesh Vutla
@ 2020-03-06 17:08   ` Tony Lindgren
  0 siblings, 0 replies; 17+ messages in thread
From: Tony Lindgren @ 2020-03-06 17:08 UTC (permalink / raw)
  To: Lokesh Vutla
  Cc: Daniel Lezcano, Thomas Gleixner, Linux OMAP Mailing List,
	linux-kernel, Thierry Reding, Uwe Kleine-König, linux-pwm,
	Sekhar Nori, Tero Kristo

* Lokesh Vutla <lokeshvutla@ti.com> [200305 08:29]:
> omap_dm_timer_ops provide support to configure the pwm but there is no
> support to get the current status. For configuring pwm it is advised to
> check the current hw status instead of relying on pwm framework. So
> implement a new timer ops to get the current status of pwm.

Acked-by: Tony Lindgen <tony@atomide.com>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm
  2020-03-05  8:27 ` [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm Lokesh Vutla
@ 2020-03-06 17:18   ` Tony Lindgren
  2020-03-30 13:18   ` Thierry Reding
  1 sibling, 0 replies; 17+ messages in thread
From: Tony Lindgren @ 2020-03-06 17:18 UTC (permalink / raw)
  To: Lokesh Vutla
  Cc: Daniel Lezcano, Thomas Gleixner, Linux OMAP Mailing List,
	linux-kernel, Thierry Reding, Uwe Kleine-König, linux-pwm,
	Sekhar Nori, Tero Kristo

* Lokesh Vutla <lokeshvutla@ti.com> [200305 08:29]:
> dm timer ops set_load() api allows to configure the load value and to
> set the auto reload feature. But auto reload feature is independent of
> load value and should be part of configuring pwm. This way pwm can be
> disabled by disabling auto reload feature using set_pwm() so that the
> current pwm cycle will be completed. Else pwm disabling causes the
> cycle to be stopped abruptly.

Acked-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates
  2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
                   ` (5 preceding siblings ...)
  2020-03-05  8:27 ` [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm Lokesh Vutla
@ 2020-03-06 17:19 ` Tony Lindgren
  2020-03-12 11:10   ` Daniel Lezcano
  6 siblings, 1 reply; 17+ messages in thread
From: Tony Lindgren @ 2020-03-06 17:19 UTC (permalink / raw)
  To: Lokesh Vutla
  Cc: Daniel Lezcano, Thomas Gleixner, Linux OMAP Mailing List,
	linux-kernel, Thierry Reding, Uwe Kleine-König, linux-pwm,
	Sekhar Nori, Tero Kristo

* Lokesh Vutla <lokeshvutla@ti.com> [200305 08:29]:
> This series fixes dm_timer_ops used for enabling the pwm and enables
> cpu_pm notifier for context save and restore. This acts as a preparatory
> series for enabling dynamic period updates for pwm omap dm timer driver.
> 
> Changes since v2:
> - Incorporated changes from Tony

I just gave this series another try here and it still works
for me just fine and is good to go as far as I'm concerned.

Thanks for doing this.

Regards,

Tony

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates
  2020-03-06 17:19 ` [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Tony Lindgren
@ 2020-03-12 11:10   ` Daniel Lezcano
  2020-03-12 17:26     ` Tony Lindgren
  0 siblings, 1 reply; 17+ messages in thread
From: Daniel Lezcano @ 2020-03-12 11:10 UTC (permalink / raw)
  To: Tony Lindgren, Lokesh Vutla
  Cc: Thomas Gleixner, Linux OMAP Mailing List, linux-kernel,
	Thierry Reding, Uwe Kleine-König, linux-pwm, Sekhar Nori,
	Tero Kristo

On 06/03/2020 18:19, Tony Lindgren wrote:
> * Lokesh Vutla <lokeshvutla@ti.com> [200305 08:29]:
>> This series fixes dm_timer_ops used for enabling the pwm and enables
>> cpu_pm notifier for context save and restore. This acts as a preparatory
>> series for enabling dynamic period updates for pwm omap dm timer driver.
>>
>> Changes since v2:
>> - Incorporated changes from Tony
> 
> I just gave this series another try here and it still works
> for me just fine and is good to go as far as I'm concerned.

How do you want this series to be merged?

Shall I pick the patches falling under drivers/clocksource or ack them?

> Thanks for doing this.
> 
> Regards,
> 
> Tony
> 


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates
  2020-03-12 11:10   ` Daniel Lezcano
@ 2020-03-12 17:26     ` Tony Lindgren
  2020-03-16 12:41       ` Daniel Lezcano
  0 siblings, 1 reply; 17+ messages in thread
From: Tony Lindgren @ 2020-03-12 17:26 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: Lokesh Vutla, Thomas Gleixner, Linux OMAP Mailing List,
	linux-kernel, Thierry Reding, Uwe Kleine-König, linux-pwm,
	Sekhar Nori, Tero Kristo

Hi,

* Daniel Lezcano <daniel.lezcano@linaro.org> [200312 11:11]:
> On 06/03/2020 18:19, Tony Lindgren wrote:
> > * Lokesh Vutla <lokeshvutla@ti.com> [200305 08:29]:
> >> This series fixes dm_timer_ops used for enabling the pwm and enables
> >> cpu_pm notifier for context save and restore. This acts as a preparatory
> >> series for enabling dynamic period updates for pwm omap dm timer driver.
> >>
> >> Changes since v2:
> >> - Incorporated changes from Tony
> > 
> > I just gave this series another try here and it still works
> > for me just fine and is good to go as far as I'm concerned.
> 
> How do you want this series to be merged?
> 
> Shall I pick the patches falling under drivers/clocksource or ack them?

I think best would be if you picked them and applied them into
an immutable branch against v5.6-rc1 that can also be merged
into pwm driver branch as needed.

Regards,

Tony

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore
  2020-03-05  8:27 ` [PATCH v3 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore Lokesh Vutla
@ 2020-03-16 10:51   ` Daniel Lezcano
  2020-03-16 11:14   ` [PATCH v4 " Lokesh Vutla
  1 sibling, 0 replies; 17+ messages in thread
From: Daniel Lezcano @ 2020-03-16 10:51 UTC (permalink / raw)
  To: Lokesh Vutla, Tony Lindgren, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo

On 05/03/2020 09:27, Lokesh Vutla wrote:
> omap_dm_timer_enable() restores the entire context(including counter)
> based on 2 conditions:
> - If get_context_loss_count is populated and context is lost.
> - If get_context_loss_count is not populated update unconditionally.
> 
> Case2 has a side effect of updating the counter register even though
> context is not lost. When timer is configured in pwm mode, this is
> causing undesired behaviour in the pwm period.
> 
> Instead of using get_context_loss_count call back, implement cpu_pm
> notifier with context save and restore support. And delete the
> get_context_loss_count callback all together.
> 
> Suggested-by: Tony Lindgren <tony@atomide.com>
> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
> [tony@atomide.com: removed pm_runtime calls from cpuidle calls]
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---

[ ... ]

> @@ -725,6 +728,12 @@ static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
>  
>  	atomic_set(&timer->enabled, 0);
>  
> +	if (timer->capability & OMAP_TIMER_ALWON ||
> +	    !timer->func_base)
> +	    return 0;

WARNING: suspect code indent for conditional statements (8, 12)
#168: FILE: drivers/clocksource/timer-ti-dm.c:762:
+	if (timer->capability & OMAP_TIMER_ALWON ||
[...]
+	    return 0;


WARNING: Statements should start on a tabstop
#170: FILE: drivers/clocksource/timer-ti-dm.c:764:
+	    return 0;

[ ... ]


Mind to resend this patch with the warning fixed?

Thanks

  -- Daniel

-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore
  2020-03-05  8:27 ` [PATCH v3 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore Lokesh Vutla
  2020-03-16 10:51   ` Daniel Lezcano
@ 2020-03-16 11:14   ` Lokesh Vutla
  1 sibling, 0 replies; 17+ messages in thread
From: Lokesh Vutla @ 2020-03-16 11:14 UTC (permalink / raw)
  To: Tony Lindgren, Daniel Lezcano, Thomas Gleixner
  Cc: Linux OMAP Mailing List, linux-kernel, Thierry Reding,
	Uwe Kleine-König, linux-pwm, Sekhar Nori, Tero Kristo,
	Lokesh Vutla, Tony Lindgren

omap_dm_timer_enable() restores the entire context(including counter)
based on 2 conditions:
- If get_context_loss_count is populated and context is lost.
- If get_context_loss_count is not populated update unconditionally.

Case2 has a side effect of updating the counter register even though
context is not lost. When timer is configured in pwm mode, this is
causing undesired behaviour in the pwm period.

Instead of using get_context_loss_count call back, implement cpu_pm
notifier with context save and restore support. And delete the
get_context_loss_count callback all together.

Suggested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[tony@atomide.com: removed pm_runtime calls from cpuidle calls]
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
Changes since v3:
- Fixed checkpatch warnings.

 drivers/clocksource/timer-ti-dm.c | 97 ++++++++++++++++++-------------
 include/clocksource/timer-ti-dm.h |  3 +-
 2 files changed, 58 insertions(+), 42 deletions(-)

diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index dae91969018d..cf4f30df99c2 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -20,6 +20,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/cpu_pm.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/device.h>
@@ -92,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
 				timer->context.tclr);
 }
 
+static void omap_timer_save_context(struct omap_dm_timer *timer)
+{
+	timer->context.tclr =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	timer->context.twer =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG);
+	timer->context.tldr =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG);
+	timer->context.tmar =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG);
+	timer->context.tier = readl_relaxed(timer->irq_ena);
+	timer->context.tsicr =
+			omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG);
+}
+
+static int omap_timer_context_notifier(struct notifier_block *nb,
+				       unsigned long cmd, void *v)
+{
+	struct omap_dm_timer *timer;
+
+	timer = container_of(nb, struct omap_dm_timer, nb);
+
+	switch (cmd) {
+	case CPU_CLUSTER_PM_ENTER:
+		if ((timer->capability & OMAP_TIMER_ALWON) ||
+		    !atomic_read(&timer->enabled))
+			break;
+		omap_timer_save_context(timer);
+		break;
+	case CPU_CLUSTER_PM_ENTER_FAILED:
+	case CPU_CLUSTER_PM_EXIT:
+		if ((timer->capability & OMAP_TIMER_ALWON) ||
+		    !atomic_read(&timer->enabled))
+			break;
+		omap_timer_restore_context(timer);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
 static int omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
 	u32 l, timeout = 100000;
@@ -179,21 +221,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 
 static void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
-	int c;
-
 	pm_runtime_get_sync(&timer->pdev->dev);
-
-	if (!(timer->capability & OMAP_TIMER_ALWON)) {
-		if (timer->get_context_loss_count) {
-			c = timer->get_context_loss_count(&timer->pdev->dev);
-			if (c != timer->ctx_loss_count) {
-				omap_timer_restore_context(timer);
-				timer->ctx_loss_count = c;
-			}
-		} else {
-			omap_timer_restore_context(timer);
-		}
-	}
 }
 
 static void omap_dm_timer_disable(struct omap_dm_timer *timer)
@@ -484,8 +512,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	}
 
-	/* Save the context */
-	timer->context.tclr = l;
 	return 0;
 }
 
@@ -501,13 +527,6 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
 
 	__omap_dm_timer_stop(timer, timer->posted, rate);
 
-	/*
-	 * Since the register values are computed and written within
-	 * __omap_dm_timer_stop, we need to use read to retrieve the
-	 * context.
-	 */
-	timer->context.tclr =
-			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -530,9 +549,6 @@ static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
-	/* Save the context */
-	timer->context.tclr = l;
-	timer->context.tldr = load;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -554,9 +570,6 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
-	/* Save the context */
-	timer->context.tclr = l;
-	timer->context.tmar = match;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -580,8 +593,6 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 	l |= trigger << 10;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
-	/* Save the context */
-	timer->context.tclr = l;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -603,8 +614,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
 	}
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 
-	/* Save the context */
-	timer->context.tclr = l;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -618,9 +627,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 	omap_dm_timer_enable(timer);
 	__omap_dm_timer_int_enable(timer, value);
 
-	/* Save the context */
-	timer->context.tier = value;
-	timer->context.twer = value;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -648,9 +654,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
 
-	/* Save the context */
-	timer->context.tier &= ~mask;
-	timer->context.twer &= ~mask;
 	omap_dm_timer_disable(timer);
 	return 0;
 }
@@ -725,6 +728,11 @@ static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev)
 
 	atomic_set(&timer->enabled, 0);
 
+	if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base)
+		return 0;
+
+	omap_timer_save_context(timer);
+
 	return 0;
 }
 
@@ -732,6 +740,9 @@ static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev)
 {
 	struct omap_dm_timer *timer = dev_get_drvdata(dev);
 
+	if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base)
+		omap_timer_restore_context(timer);
+
 	atomic_set(&timer->enabled, 1);
 
 	return 0;
@@ -798,7 +809,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
 		timer->id = pdev->id;
 		timer->capability = pdata->timer_capability;
 		timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
-		timer->get_context_loss_count = pdata->get_context_loss_count;
+	}
+
+	if (!(timer->capability & OMAP_TIMER_ALWON)) {
+		timer->nb.notifier_call = omap_timer_context_notifier;
+		cpu_pm_register_notifier(&timer->nb);
 	}
 
 	if (pdata)
@@ -852,6 +867,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
 	list_for_each_entry(timer, &omap_timer_list, node)
 		if (!strcmp(dev_name(&timer->pdev->dev),
 			    dev_name(&pdev->dev))) {
+			if (!(timer->capability & OMAP_TIMER_ALWON))
+				cpu_pm_unregister_notifier(&timer->nb);
 			list_del(&timer->node);
 			ret = 0;
 			break;
diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h
index eef5de300731..25f05235866e 100644
--- a/include/clocksource/timer-ti-dm.h
+++ b/include/clocksource/timer-ti-dm.h
@@ -110,13 +110,12 @@ struct omap_dm_timer {
 	unsigned reserved:1;
 	unsigned posted:1;
 	struct timer_regs context;
-	int (*get_context_loss_count)(struct device *);
-	int ctx_loss_count;
 	int revision;
 	u32 capability;
 	u32 errata;
 	struct platform_device *pdev;
 	struct list_head node;
+	struct notifier_block nb;
 };
 
 int omap_dm_timer_reserve_systimer(int id);
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates
  2020-03-12 17:26     ` Tony Lindgren
@ 2020-03-16 12:41       ` Daniel Lezcano
  0 siblings, 0 replies; 17+ messages in thread
From: Daniel Lezcano @ 2020-03-16 12:41 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Lokesh Vutla, Thomas Gleixner, Linux OMAP Mailing List,
	linux-kernel, Thierry Reding, Uwe Kleine-König, linux-pwm,
	Sekhar Nori, Tero Kristo


Hi Tony,

On 12/03/2020 18:26, Tony Lindgren wrote:
> Hi,
> 
> * Daniel Lezcano <daniel.lezcano@linaro.org> [200312 11:11]:
>> On 06/03/2020 18:19, Tony Lindgren wrote:
>>> * Lokesh Vutla <lokeshvutla@ti.com> [200305 08:29]:
>>>> This series fixes dm_timer_ops used for enabling the pwm and enables
>>>> cpu_pm notifier for context save and restore. This acts as a preparatory
>>>> series for enabling dynamic period updates for pwm omap dm timer driver.
>>>>
>>>> Changes since v2:
>>>> - Incorporated changes from Tony
>>>
>>> I just gave this series another try here and it still works
>>> for me just fine and is good to go as far as I'm concerned.
>>
>> How do you want this series to be merged?
>>
>> Shall I pick the patches falling under drivers/clocksource or ack them?
> 
> I think best would be if you picked them and applied them into
> an immutable branch against v5.6-rc1 that can also be merged
> into pwm driver branch as needed.

Immutable branch based on v5.6-rc1:


https://git.linaro.org/people/dlezcano/linux.git/log/?h=timers/drivers/timer-ti-dm

and merged to timers/drivers/next:


https://git.linaro.org/people/dlezcano/linux.git/log/?h=timers/drivers/next

with a small conflict (fixed) with:


https://git.linaro.org/people/dlezcano/linux.git/commit/?h=timers/drivers/next&id=6ce4fcb015a1a1290ffafcf3554901b40f9322df

Regards

  -- Daniel

-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm
  2020-03-05  8:27 ` [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm Lokesh Vutla
  2020-03-06 17:18   ` Tony Lindgren
@ 2020-03-30 13:18   ` Thierry Reding
  1 sibling, 0 replies; 17+ messages in thread
From: Thierry Reding @ 2020-03-30 13:18 UTC (permalink / raw)
  To: Lokesh Vutla
  Cc: Tony Lindgren, Daniel Lezcano, Thomas Gleixner,
	Linux OMAP Mailing List, linux-kernel, Uwe Kleine-König,
	linux-pwm, Sekhar Nori, Tero Kristo

[-- Attachment #1: Type: text/plain, Size: 820 bytes --]

On Thu, Mar 05, 2020 at 01:57:15PM +0530, Lokesh Vutla wrote:
> dm timer ops set_load() api allows to configure the load value and to
> set the auto reload feature. But auto reload feature is independent of
> load value and should be part of configuring pwm. This way pwm can be
> disabled by disabling auto reload feature using set_pwm() so that the
> current pwm cycle will be completed. Else pwm disabling causes the
> cycle to be stopped abruptly.
> 
> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
> ---
>  drivers/clocksource/timer-ti-dm.c          | 16 +++++-----------
>  drivers/pwm/pwm-omap-dmtimer.c             |  8 +++++---
>  include/linux/platform_data/dmtimer-omap.h |  5 ++---
>  3 files changed, 12 insertions(+), 17 deletions(-)

Acked-by: Thierry Reding <thierry.reding@gmail.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2020-03-30 13:18 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-05  8:27 [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Lokesh Vutla
2020-03-05  8:27 ` [PATCH v3 1/6] clocksource: timer-ti-dm: Convert to SPDX identifier Lokesh Vutla
2020-03-06 16:57   ` Tony Lindgren
2020-03-05  8:27 ` [PATCH v3 2/6] clocksource: timer-ti-dm: Prepare for using cpuidle Lokesh Vutla
2020-03-05  8:27 ` [PATCH v3 3/6] clocksource: timer-ti-dm: Implement cpu_pm notifier for context save and restore Lokesh Vutla
2020-03-16 10:51   ` Daniel Lezcano
2020-03-16 11:14   ` [PATCH v4 " Lokesh Vutla
2020-03-05  8:27 ` [PATCH v3 4/6] clocksource: timer-ti-dm: Do not update counter on updating the period Lokesh Vutla
2020-03-05  8:27 ` [PATCH v3 5/6] clocksource: timer-ti-dm: Add support to get pwm current status Lokesh Vutla
2020-03-06 17:08   ` Tony Lindgren
2020-03-05  8:27 ` [PATCH v3 6/6] clocksource: timer-ti-dm: Enable autoreload in set_pwm Lokesh Vutla
2020-03-06 17:18   ` Tony Lindgren
2020-03-30 13:18   ` Thierry Reding
2020-03-06 17:19 ` [PATCH v3 0/6] clocksource: timer-ti-dm: Prepare for dynamic pwm period updates Tony Lindgren
2020-03-12 11:10   ` Daniel Lezcano
2020-03-12 17:26     ` Tony Lindgren
2020-03-16 12:41       ` Daniel Lezcano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).