pwm: stm32: Add power management support

Add suspend/resume PM sleep ops. When going to low power, enforce the PWM
channel isn't active. Let the PWM consumers disable it during their own
suspend sequence, see [1]. So, perform a check here, and handle the
pinctrl states. Also restore the break inputs upon resume, as registers
content may be lost when going to low power mode.

[1] https://lkml.org/lkml/2019/2/5/770

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
This commit is contained in:
Fabrice Gasnier 2019-10-04 14:53:53 +02:00 коммит произвёл Thierry Reding
Родитель 0f9d2ecba8
Коммит 2d3aa06b5d
1 изменённых файлов: 38 добавлений и 0 удалений

Просмотреть файл

@ -12,6 +12,7 @@
#include <linux/mfd/stm32-timers.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
@ -659,6 +660,42 @@ static int stm32_pwm_remove(struct platform_device *pdev)
return 0;
}
static int __maybe_unused stm32_pwm_suspend(struct device *dev)
{
struct stm32_pwm *priv = dev_get_drvdata(dev);
unsigned int i;
u32 ccer, mask;
/* Look for active channels */
ccer = active_channels(priv);
for (i = 0; i < priv->chip.npwm; i++) {
mask = TIM_CCER_CC1E << (i * 4);
if (ccer & mask) {
dev_err(dev, "PWM %u still in use by consumer %s\n",
i, priv->chip.pwms[i].label);
return -EBUSY;
}
}
return pinctrl_pm_select_sleep_state(dev);
}
static int __maybe_unused stm32_pwm_resume(struct device *dev)
{
struct stm32_pwm *priv = dev_get_drvdata(dev);
int ret;
ret = pinctrl_pm_select_default_state(dev);
if (ret)
return ret;
/* restore breakinput registers that may have been lost in low power */
return stm32_pwm_apply_breakinputs(priv);
}
static SIMPLE_DEV_PM_OPS(stm32_pwm_pm_ops, stm32_pwm_suspend, stm32_pwm_resume);
static const struct of_device_id stm32_pwm_of_match[] = {
{ .compatible = "st,stm32-pwm", },
{ /* end node */ },
@ -671,6 +708,7 @@ static struct platform_driver stm32_pwm_driver = {
.driver = {
.name = "stm32-pwm",
.of_match_table = stm32_pwm_of_match,
.pm = &stm32_pwm_pm_ops,
},
};
module_platform_driver(stm32_pwm_driver);