From f9bb9da7c09d76f00c9abdf34cbeaec65e50d78b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 1 Mar 2017 15:52:27 +0100 Subject: [PATCH] pwm: atmel-hlcdc: Implement the suspend/resume hooks Implement the suspend/resume hooks to make sure the PWM device is restored to a correct state after a suspend. Signed-off-by: Boris Brezillon Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel-hlcdc.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index bcb6d94..54c6633 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c @@ -191,6 +191,40 @@ static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_sama5d3_errata = { .div1_clk_erratum = true, }; +#ifdef CONFIG_PM_SLEEP +static int atmel_hlcdc_pwm_suspend(struct device *dev) +{ + struct atmel_hlcdc_pwm *chip = dev_get_drvdata(dev); + + /* Keep the periph clock enabled if the PWM is still running. */ + if (pwm_is_enabled(&chip->chip.pwms[0])) + clk_disable_unprepare(chip->hlcdc->periph_clk); + + return 0; +} + +static int atmel_hlcdc_pwm_resume(struct device *dev) +{ + struct atmel_hlcdc_pwm *chip = dev_get_drvdata(dev); + struct pwm_state state; + int ret; + + pwm_get_state(&chip->chip.pwms[0], &state); + + /* Re-enable the periph clock it was stopped during suspend. */ + if (!state.enabled) { + ret = clk_prepare_enable(chip->hlcdc->periph_clk); + if (ret) + return ret; + } + + return atmel_hlcdc_pwm_apply(&chip->chip, &chip->chip.pwms[0], &state); +} +#endif + +static SIMPLE_DEV_PM_OPS(atmel_hlcdc_pwm_pm_ops, + atmel_hlcdc_pwm_suspend, atmel_hlcdc_pwm_resume); + static const struct of_device_id atmel_hlcdc_dt_ids[] = { { .compatible = "atmel,at91sam9n12-hlcdc", @@ -280,6 +314,7 @@ static struct platform_driver atmel_hlcdc_pwm_driver = { .driver = { .name = "atmel-hlcdc-pwm", .of_match_table = atmel_hlcdc_pwm_dt_ids, + .pm = &atmel_hlcdc_pwm_pm_ops, }, .probe = atmel_hlcdc_pwm_probe, .remove = atmel_hlcdc_pwm_remove, -- 2.7.4