[PATCH] ARM: SAMSUNG: Add suspend/resume support for S3C PWM driver
Lars-Peter Clausen
lars at metafoo.de
Mon Mar 15 15:36:05 EDT 2010
Vasily Khoruzhick wrote:
> Reset period_ns and duty_ns values in suspend handler to avoid skip of
> configuration if same values passed to pwm_config;
> Restore invertion bit in resume handler.
>
> Without this patch PWM works incorrectly after resume from suspend.
>
> Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
>
Hi
There is still one big issue left regarding pwm suspend/resume.
If the invert bit is not set, the pwm will generate a HIGH signal when
being inactive, when the bit is set it will generate a HIGH signal when
active.
As a result any pin to which the pwm signal is routed will appear as
active until the pwm resume handler is called. This usually takes a few
100 ms seconds and so for a short period of time we'll get the wrong
signal on pwm pins.
For correct behavior the pwm driver would have to check all pins to
which it's signal might be routed and if it's actually is configure the
pin as LOW output.
Upon resume the pin then has to be reconfigured as a pwm pin, only after
the invert bit has been set.
I know that it previously has been stated, that it is not desired for
the pwm driver to know about gpio pins. But in my opinion to ensure
correct behavior it is unavoidable.
- Lars
> ---
> arch/arm/plat-samsung/pwm.c | 35 +++++++++++++++++++++++++++++++++++
> 1 files changed, 35 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c
> index ef019f2..f2d1139 100644
> --- a/arch/arm/plat-samsung/pwm.c
> +++ b/arch/arm/plat-samsung/pwm.c
> @@ -379,6 +379,39 @@ static int __devexit s3c_pwm_remove(struct platform_device *pdev)
> return 0;
> }
>
> +#ifdef CONFIG_PM
> +static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + struct pwm_device *pwm = platform_get_drvdata(pdev);
> +
> + /* No one preserve these values during suspend so reset them
> + * Otherwise driver leaves PWM unconfigured if same values
> + * passed to pwm_config
> + */
> + pwm->period_ns = 0;
> + pwm->duty_ns = 0;
> +
> + return 0;
> +}
> +
> +static int s3c_pwm_resume(struct platform_device *pdev)
> +{
> + struct pwm_device *pwm = platform_get_drvdata(pdev);
> + unsigned long tcon;
> +
> + /* Restore invertion */
> + tcon = __raw_readl(S3C2410_TCON);
> + tcon |= pwm_tcon_invert(pwm);
> + __raw_writel(tcon, S3C2410_TCON);
> +
> + return 0;
> +}
> +
> +#else
> +#define s3c_pwm_suspend NULL
> +#define s3c_pwm_resume NULL
> +#endif
> +
> static struct platform_driver s3c_pwm_driver = {
> .driver = {
> .name = "s3c24xx-pwm",
> @@ -386,6 +419,8 @@ static struct platform_driver s3c_pwm_driver = {
> },
> .probe = s3c_pwm_probe,
> .remove = __devexit_p(s3c_pwm_remove),
> + .suspend = s3c_pwm_suspend,
> + .resume = s3c_pwm_resume,
> };
>
> static int __init pwm_init(void)
>
More information about the linux-arm-kernel
mailing list