linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] drivers: pwm: pwm-atmel: implement suspend/resume functions
@ 2017-04-10 14:20 Claudiu Beznea
  2017-04-10 14:35 ` Boris Brezillon
  0 siblings, 1 reply; 14+ messages in thread
From: Claudiu Beznea @ 2017-04-10 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

Implement suspend and resume power management specific
function to allow PWM controller to correctly suspend
and resume.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 drivers/pwm/pwm-atmel.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 530d7dc..75177c6 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -58,6 +58,8 @@
 #define PWM_MAX_PRD		0xFFFF
 #define PRD_MAX_PRES		10
 
+#define PWM_MAX_CH_NUM		(4)
+
 struct atmel_pwm_registers {
 	u8 period;
 	u8 period_upd;
@@ -65,11 +67,18 @@ struct atmel_pwm_registers {
 	u8 duty_upd;
 };
 
+struct atmel_pwm_pm_ctx {
+	u32 cmr;
+	u32 cdty;
+	u32 cprd;
+};
+
 struct atmel_pwm_chip {
 	struct pwm_chip chip;
 	struct clk *clk;
 	void __iomem *base;
 	const struct atmel_pwm_registers *regs;
+	struct atmel_pwm_pm_ctx ctx[PWM_MAX_CH_NUM];
 
 	unsigned int updated_pwms;
 	/* ISR is cleared when read, ensure only one thread does that */
@@ -333,6 +342,77 @@ atmel_pwm_get_driver_data(struct platform_device *pdev)
 	return (struct atmel_pwm_registers *)id->driver_data;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int atmel_pwm_suspend(struct device *dev)
+{
+	struct atmel_pwm_chip *atmel_pwm = dev_get_drvdata(dev);
+	struct pwm_device *pwm = atmel_pwm->chip.pwms;
+	int i;
+	bool disable_clk = false;
+
+	for (i = 0; i < atmel_pwm->chip.npwm; i++, pwm++) {
+		if (!pwm_is_enabled(pwm))
+			continue;
+
+		disable_clk = true;
+		atmel_pwm->ctx[i].cdty =
+			atmel_pwm_ch_readl(atmel_pwm, i,
+					   atmel_pwm->regs->duty);
+		atmel_pwm->ctx[i].cprd =
+			atmel_pwm_ch_readl(atmel_pwm, i,
+					   atmel_pwm->regs->period);
+		atmel_pwm->ctx[i].cmr =
+			atmel_pwm_ch_readl(atmel_pwm, i, PWM_CMR);
+
+		atmel_pwm_disable(&atmel_pwm->chip, pwm, false);
+	}
+
+	if (disable_clk)
+		clk_disable(atmel_pwm->clk);
+
+	return 0;
+}
+
+static int atmel_pwm_resume(struct device *dev)
+{
+	struct atmel_pwm_chip *atmel_pwm = dev_get_drvdata(dev);
+	struct pwm_device *pwm = atmel_pwm->chip.pwms;
+	int i, ret;
+	bool disable_clk = true;
+
+	ret = clk_enable(atmel_pwm->clk);
+	if (ret) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	for (i = 0; i < atmel_pwm->chip.npwm; i++, pwm++) {
+		if (!pwm_is_enabled(pwm))
+			continue;
+
+		disable_clk = false;
+		atmel_pwm_ch_writel(atmel_pwm, i, PWM_CMR,
+				    atmel_pwm->ctx[i].cmr);
+		atmel_pwm_set_cprd_cdty(&atmel_pwm->chip, pwm,
+					atmel_pwm->ctx[i].cprd,
+					atmel_pwm->ctx[i].cdty);
+		mutex_lock(&atmel_pwm->isr_lock);
+		atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
+		atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm);
+		mutex_unlock(&atmel_pwm->isr_lock);
+		atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
+	}
+
+	if (disable_clk)
+		clk_disable(atmel_pwm->clk);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(atmel_pwm_pm_ops,
+			 atmel_pwm_suspend, atmel_pwm_resume);
+
 static int atmel_pwm_probe(struct platform_device *pdev)
 {
 	const struct atmel_pwm_registers *regs;
@@ -406,6 +486,7 @@ static struct platform_driver atmel_pwm_driver = {
 	.driver = {
 		.name = "atmel-pwm",
 		.of_match_table = of_match_ptr(atmel_pwm_dt_ids),
+		.pm = &atmel_pwm_pm_ops,
 	},
 	.id_table = atmel_pwm_devtypes,
 	.probe = atmel_pwm_probe,
-- 
2.7.4

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

end of thread, other threads:[~2018-01-11 13:51 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-10 14:20 [PATCH] drivers: pwm: pwm-atmel: implement suspend/resume functions Claudiu Beznea
2017-04-10 14:35 ` Boris Brezillon
2017-04-10 15:10   ` Thierry Reding
2017-04-10 16:01     ` Boris Brezillon
2017-04-10 16:27       ` Boris Brezillon
2017-04-11  8:33         ` m18063
2017-04-11  8:50           ` Boris Brezillon
2017-04-11  8:59             ` m18063
2017-04-11  8:22   ` m18063
2017-04-11  8:56     ` Boris Brezillon
2017-04-11  9:41       ` m18063
2017-04-11  9:53         ` Boris Brezillon
2017-12-05  9:06           ` Thierry Reding
2018-01-11 13:51             ` Claudiu Beznea

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).