pwm: lpss: Use DPM_FLAG_NO_DIRECT_COMPLETE instead of declaring a prepare handler
authorHans de Goede <hdegoede@redhat.com>
Mon, 9 Nov 2020 10:57:25 +0000 (11:57 +0100)
committerThierry Reding <thierry.reding@gmail.com>
Thu, 17 Dec 2020 13:18:48 +0000 (14:18 +0100)
ACPI LPSS devices use direct-complete style suspend/resume handling by
default. We set the DPM_FLAG_SMART_PREPARE and define a prepare handler
to disable this on Cherry Trail devices.

Clean this up a bit by setting the DPM_FLAG_NO_DIRECT_COMPLETE flag for
Cherry Trail devices, instead of defining a prepare handler.

While at it also improve the comment explaining why this is necessary.

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
drivers/pwm/pwm-lpss-platform.c

index c6502cf7a7af1f389747ff914564f9e68be2c349..ac33861edb481f2e5ee837341964f41b3957f13a 100644 (file)
@@ -58,7 +58,21 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, lpwm);
 
-       dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);
+       /*
+        * On Cherry Trail devices the GFX0._PS0 AML checks if the controller
+        * is on and if it is not on it turns it on and restores what it
+        * believes is the correct state to the PWM controller.
+        * Because of this we must disallow direct-complete, which keeps the
+        * controller (runtime)suspended on resume, to avoid 2 issues:
+        * 1. The controller getting turned on without the linux-pm code
+        *    knowing about this. On devices where the controller is unused
+        *    this causes it to stay on during the next suspend causing high
+        *    battery drain (because S0i3 is not reached)
+        * 2. The state restoring code unexpectedly messing with the controller
+        */
+       if (info->other_devices_aml_touches_pwm_regs)
+               dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
 
@@ -73,24 +87,6 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
        return pwm_lpss_remove(lpwm);
 }
 
-static int pwm_lpss_prepare(struct device *dev)
-{
-       struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
-
-       /*
-        * If other device's AML code touches the PWM regs on suspend/resume
-        * force runtime-resume the PWM controller to allow this.
-        */
-       if (lpwm->info->other_devices_aml_touches_pwm_regs)
-               return 0; /* Force runtime-resume */
-
-       return 1; /* If runtime-suspended leave as is */
-}
-
-static const struct dev_pm_ops pwm_lpss_platform_pm_ops = {
-       .prepare = pwm_lpss_prepare,
-};
-
 static const struct acpi_device_id pwm_lpss_acpi_match[] = {
        { "80860F09", (unsigned long)&pwm_lpss_byt_info },
        { "80862288", (unsigned long)&pwm_lpss_bsw_info },
@@ -104,7 +100,6 @@ static struct platform_driver pwm_lpss_driver_platform = {
        .driver = {
                .name = "pwm-lpss",
                .acpi_match_table = pwm_lpss_acpi_match,
-               .pm = &pwm_lpss_platform_pm_ops,
        },
        .probe = pwm_lpss_probe_platform,
        .remove = pwm_lpss_remove_platform,