Commit 736e19e6 authored by Fabrice Gasnier's avatar Fabrice Gasnier Committed by Jonathan Cameron

iio: trigger: stm32-timer: add power management support

Add suspend/resume PM sleep ops to stm32-timer-trigger driver.
Register contents may be lost depending on low power modes.
When going to low power, enforce the timer isn't active. Gracefully
restore its state upon resume in case it's been left enabled prior to
suspend.
Signed-off-by: default avatarFabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent e23aaafc
......@@ -75,6 +75,15 @@ static const void *stm32h7_valids_table[][MAX_VALIDS] = {
{ }, /* timer 17 */
};
struct stm32_timer_trigger_regs {
u32 cr1;
u32 cr2;
u32 psc;
u32 arr;
u32 cnt;
u32 smcr;
};
struct stm32_timer_trigger {
struct device *dev;
struct regmap *regmap;
......@@ -86,6 +95,7 @@ struct stm32_timer_trigger {
bool has_trgo2;
struct mutex lock; /* concurrent sysfs configuration */
struct list_head tr_list;
struct stm32_timer_trigger_regs bak;
};
struct stm32_timer_trigger_cfg {
......@@ -812,6 +822,58 @@ static int stm32_timer_trigger_remove(struct platform_device *pdev)
return 0;
}
static int __maybe_unused stm32_timer_trigger_suspend(struct device *dev)
{
struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
/* Only take care of enabled timer: don't disturb other MFD child */
if (priv->enabled) {
/* Backup registers that may get lost in low power mode */
regmap_read(priv->regmap, TIM_CR1, &priv->bak.cr1);
regmap_read(priv->regmap, TIM_CR2, &priv->bak.cr2);
regmap_read(priv->regmap, TIM_PSC, &priv->bak.psc);
regmap_read(priv->regmap, TIM_ARR, &priv->bak.arr);
regmap_read(priv->regmap, TIM_CNT, &priv->bak.cnt);
regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr);
/* Disable the timer */
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
clk_disable(priv->clk);
}
return 0;
}
static int __maybe_unused stm32_timer_trigger_resume(struct device *dev)
{
struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
int ret;
if (priv->enabled) {
ret = clk_enable(priv->clk);
if (ret)
return ret;
/* restore master/slave modes */
regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
regmap_write(priv->regmap, TIM_CR2, priv->bak.cr2);
/* restore sampling_frequency (trgo / trgo2 triggers) */
regmap_write(priv->regmap, TIM_PSC, priv->bak.psc);
regmap_write(priv->regmap, TIM_ARR, priv->bak.arr);
regmap_write(priv->regmap, TIM_CNT, priv->bak.cnt);
/* Also re-enables the timer */
regmap_write(priv->regmap, TIM_CR1, priv->bak.cr1);
}
return 0;
}
static SIMPLE_DEV_PM_OPS(stm32_timer_trigger_pm_ops,
stm32_timer_trigger_suspend,
stm32_timer_trigger_resume);
static const struct stm32_timer_trigger_cfg stm32_timer_trg_cfg = {
.valids_table = valids_table,
.num_valids_table = ARRAY_SIZE(valids_table),
......@@ -840,6 +902,7 @@ static struct platform_driver stm32_timer_trigger_driver = {
.driver = {
.name = "stm32-timer-trigger",
.of_match_table = stm32_trig_of_match,
.pm = &stm32_timer_trigger_pm_ops,
},
};
module_platform_driver(stm32_timer_trigger_driver);
......
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