e336be
From 9e2ef73d9d72ab312bef34ba318fdcb77facb1f0 Mon Sep 17 00:00:00 2001
e336be
From: Hans de Goede <hdegoede@redhat.com>
e336be
Date: Mon, 27 Aug 2018 09:47:42 +0200
e336be
Subject: [PATCH 1/7] pwm: lpss: Add ACPI HID for second PWM controller on
e336be
 Cherry Trail devices
e336be
e336be
The second PWM controller on Cherry Trail devices uses a separate ACPI
e336be
HID: "80862289", add this so that the driver will properly bind to the
e336be
second PWM controller.
e336be
e336be
The second PWM controller is usually not used, the main thing gained by
e336be
this is properly putting the PWM controller in D3 on suspend.
e336be
e336be
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
e336be
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
e336be
---
e336be
 drivers/pwm/pwm-lpss-platform.c | 1 +
e336be
 1 file changed, 1 insertion(+)
e336be
e336be
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
e336be
index 5561b9e190f8..7304f36ee715 100644
e336be
--- a/drivers/pwm/pwm-lpss-platform.c
e336be
+++ b/drivers/pwm/pwm-lpss-platform.c
e336be
@@ -81,6 +81,7 @@ static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops,
e336be
 static const struct acpi_device_id pwm_lpss_acpi_match[] = {
e336be
 	{ "80860F09", (unsigned long)&pwm_lpss_byt_info },
e336be
 	{ "80862288", (unsigned long)&pwm_lpss_bsw_info },
e336be
+	{ "80862289", (unsigned long)&pwm_lpss_bsw_info },
e336be
 	{ "80865AC8", (unsigned long)&pwm_lpss_bxt_info },
e336be
 	{ },
e336be
 };
e336be
-- 
e336be
2.19.1
e336be
e336be
From f215ee5bd62ab40ee34c318df1af61991dead98d Mon Sep 17 00:00:00 2001
e336be
From: Hans de Goede <hdegoede@redhat.com>
e336be
Date: Tue, 11 Sep 2018 16:07:41 +0200
e336be
Subject: [PATCH 2/7] pwm: lpss: Move struct pwm_lpss_chip definition to the
e336be
 header file
e336be
e336be
Move struct pwm_lpss_chip definition from pwm-lpss.c to pwm-lpss.h,
e336be
so that the pci/platform drivers can access the info member
e336be
(struct pwm_lpss_boardinfo *).
e336be
e336be
This is a preparation patch for adding platform specific quirks, which
e336be
the drivers need access to, to pwm_lpss_boardinfo.
e336be
e336be
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
e336be
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
e336be
---
e336be
Changes in v4:
e336be
-No changes in v4 of this patch-set
e336be
e336be
Changes in v3:
e336be
-There was no v3, but I accidentally put v3 in the Subject of the v2
e336be
 patches, so lets skip v3
e336be
e336be
Changes in v2:
e336be
-No changes in v2 of this patch-set
e336be
---
e336be
 drivers/pwm/pwm-lpss.c | 9 ---------
e336be
 drivers/pwm/pwm-lpss.h | 9 ++++++++-
e336be
 2 files changed, 8 insertions(+), 10 deletions(-)
e336be
e336be
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
e336be
index 4721a264bac2..e602835fd6de 100644
e336be
--- a/drivers/pwm/pwm-lpss.c
e336be
+++ b/drivers/pwm/pwm-lpss.c
e336be
@@ -32,15 +32,6 @@
e336be
 /* Size of each PWM register space if multiple */
e336be
 #define PWM_SIZE			0x400
e336be
 
e336be
-#define MAX_PWMS			4
e336be
-
e336be
-struct pwm_lpss_chip {
e336be
-	struct pwm_chip chip;
e336be
-	void __iomem *regs;
e336be
-	const struct pwm_lpss_boardinfo *info;
e336be
-	u32 saved_ctrl[MAX_PWMS];
e336be
-};
e336be
-
e336be
 static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
e336be
 {
e336be
 	return container_of(chip, struct pwm_lpss_chip, chip);
e336be
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
e336be
index 7a4238ad1fcb..8f029ed263af 100644
e336be
--- a/drivers/pwm/pwm-lpss.h
e336be
+++ b/drivers/pwm/pwm-lpss.h
e336be
@@ -16,7 +16,14 @@
e336be
 #include <linux/device.h>
e336be
 #include <linux/pwm.h>
e336be
 
e336be
-struct pwm_lpss_chip;
e336be
+#define MAX_PWMS			4
e336be
+
e336be
+struct pwm_lpss_chip {
e336be
+	struct pwm_chip chip;
e336be
+	void __iomem *regs;
e336be
+	const struct pwm_lpss_boardinfo *info;
e336be
+	u32 saved_ctrl[MAX_PWMS];
e336be
+};
e336be
 
e336be
 struct pwm_lpss_boardinfo {
e336be
 	unsigned long clk_rate;
e336be
-- 
e336be
2.19.1
e336be
e336be
From eb73756876f92ad0da4259400bce50881cb332b7 Mon Sep 17 00:00:00 2001
e336be
From: Hans de Goede <hdegoede@redhat.com>
e336be
Date: Mon, 10 Sep 2018 15:30:58 +0200
e336be
Subject: [PATCH 3/7] pwm: lpss: Check PWM powerstate after resume on Cherry
e336be
 Trail devices
e336be
e336be
The _PS0 method for the integrated graphics on some Cherry Trail devices
e336be
(observed on a HP Pavilion X2 10-p0XX) turns on the PWM chip (puts it in
e336be
D0), causing an inconsistency between the state the pm-core thinks it is
e336be
in (left runtime suspended as it was before the suspend/resume) and the
e336be
state it actually is in.
e336be
e336be
Interestingly enough this is done on a device where the pwm controller is
e336be
not used for the backlight at all, since it uses an eDP panel. On devices
e336be
where the PWM is used this is not a problem since we will resume it
e336be
ourselves anyways.
e336be
e336be
This inconsistency causes us to never suspend the pwm controller again,
e336be
which causes the device to not be able to reach S0ix states when suspended.
e336be
e336be
This commit adds a resume-complete handler, which when we think the device
e336be
is still run-time suspended checks the actual power-state and if necessary
e336be
updates the rpm-core's internal state.
e336be
e336be
This fixes the Pavilion X2 10-p0XX not reaching S0ix states when suspended.
e336be
e336be
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
e336be
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
e336be
---
e336be
Changes in v4:
e336be
-Use acpi_device_get_power() instead of manually calling _PSC
e336be
e336be
Changes in v3:
e336be
-There was no v3, but I accidentally put v3 in the Subject of the v2
e336be
 patches, so lets skip v3
e336be
e336be
Changes in v2:
e336be
-Do the pm_runtime_en/disable before/after checking the power-state
e336be
---
e336be
 drivers/pwm/pwm-lpss-platform.c | 25 ++++++++++++++++++++++---
e336be
 drivers/pwm/pwm-lpss.h          |  2 ++
e336be
 2 files changed, 24 insertions(+), 3 deletions(-)
e336be
e336be
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
e336be
index 7304f36ee715..b6edf8af26cc 100644
e336be
--- a/drivers/pwm/pwm-lpss-platform.c
e336be
+++ b/drivers/pwm/pwm-lpss-platform.c
e336be
@@ -30,6 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
e336be
 	.clk_rate = 19200000,
e336be
 	.npwm = 1,
e336be
 	.base_unit_bits = 16,
e336be
+	.check_power_on_resume = true,
e336be
 };
e336be
 
e336be
 /* Broxton */
e336be
@@ -74,9 +75,27 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
e336be
 	return pwm_lpss_remove(lpwm);
e336be
 }
e336be
 
e336be
-static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops,
e336be
-			 pwm_lpss_suspend,
e336be
-			 pwm_lpss_resume);
e336be
+static void pwm_lpss_complete(struct device *dev)
e336be
+{
e336be
+	struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
e336be
+	int ret, state;
e336be
+
e336be
+	/* The PWM may be turned on by AML code, update our state to match */
e336be
+	if (pm_runtime_suspended(dev) && lpwm->info->check_power_on_resume) {
e336be
+		pm_runtime_disable(dev);
e336be
+
e336be
+		ret = acpi_device_get_power(ACPI_COMPANION(dev), &state);
e336be
+		if (ret == 0 && state == ACPI_STATE_D0)
e336be
+			pm_runtime_set_active(dev);
e336be
+
e336be
+		pm_runtime_enable(dev);
e336be
+	}
e336be
+}
e336be
+
e336be
+static const struct dev_pm_ops pwm_lpss_platform_pm_ops = {
e336be
+	.complete = pwm_lpss_complete,
e336be
+	SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume)
e336be
+};
e336be
 
e336be
 static const struct acpi_device_id pwm_lpss_acpi_match[] = {
e336be
 	{ "80860F09", (unsigned long)&pwm_lpss_byt_info },
e336be
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
e336be
index 8f029ed263af..1a2575d25bea 100644
e336be
--- a/drivers/pwm/pwm-lpss.h
e336be
+++ b/drivers/pwm/pwm-lpss.h
e336be
@@ -30,6 +30,8 @@ struct pwm_lpss_boardinfo {
e336be
 	unsigned int npwm;
e336be
 	unsigned long base_unit_bits;
e336be
 	bool bypass;
e336be
+	/* Some devices have AML code messing with the state underneath us */
e336be
+	bool check_power_on_resume;
e336be
 };
e336be
 
e336be
 struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
e336be
-- 
e336be
2.19.1
e336be
e336be
From 0a2e85765305e9fc376d0153aa9747b5d58cc804 Mon Sep 17 00:00:00 2001
e336be
From: Hans de Goede <hdegoede@redhat.com>
e336be
Date: Mon, 24 Sep 2018 20:57:43 +0200
e336be
Subject: [PATCH 4/7] pwm: lpss: Release runtime-pm reference from the driver's
e336be
 remove callback
e336be
e336be
For each pwm output which gets enabled through pwm_lpss_apply(), we do a
e336be
pm_runtime_get_sync().
e336be
e336be
This commit adds pm_runtime_put() calls to pwm_lpss_remove() to balance
e336be
these when the driver gets removed with some of the outputs still enabled.
e336be
e336be
Fixes: f080be27d7d9 ("pwm: lpss: Add support for runtime PM")
e336be
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
e336be
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
e336be
---
e336be
Changes in v2:
e336be
-New patch in v2 of this patch-set replacing "pwm: lpss: Add
e336be
 pwm_lpss_get_put_runtime_pm helper function"
e336be
---
e336be
 drivers/pwm/pwm-lpss.c | 6 ++++++
e336be
 1 file changed, 6 insertions(+)
e336be
e336be
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
e336be
index e602835fd6de..723ca9de8325 100644
e336be
--- a/drivers/pwm/pwm-lpss.c
e336be
+++ b/drivers/pwm/pwm-lpss.c
e336be
@@ -205,6 +205,12 @@ EXPORT_SYMBOL_GPL(pwm_lpss_probe);
e336be
 
e336be
 int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
e336be
 {
e336be
+	int i;
e336be
+
e336be
+	for (i = 0; i < lpwm->info->npwm; i++) {
e336be
+		if (pwm_is_enabled(&lpwm->chip.pwms[i]))
e336be
+			pm_runtime_put(lpwm->chip.dev);
e336be
+	}
e336be
 	return pwmchip_remove(&lpwm->chip);
e336be
 }
e336be
 EXPORT_SYMBOL_GPL(pwm_lpss_remove);
e336be
-- 
e336be
2.19.1
e336be
e336be
From c3ffc28eeb4f9974380c4a85abfbb387d6d1cd8d Mon Sep 17 00:00:00 2001
e336be
From: Hans de Goede <hdegoede@redhat.com>
e336be
Date: Fri, 25 Nov 2016 09:45:19 +0100
e336be
Subject: [PATCH 5/7] pwm: lpss: Add get_state callback
e336be
e336be
Add a get_state callback so that the initial state correctly reflects
e336be
the actual hardware state.
e336be
e336be
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
e336be
Acked-by: Jani Nikula <jani.nikula@intel.com>
e336be
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
e336be
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
e336be
---
e336be
Changes in v2:
e336be
-Stop using the dropped pwm_lpss_get_put_runtime_pm() helper
e336be
---
e336be
 drivers/pwm/pwm-lpss.c | 34 ++++++++++++++++++++++++++++++++++
e336be
 1 file changed, 34 insertions(+)
e336be
e336be
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
e336be
index 723ca9de8325..ea93ef9f3672 100644
e336be
--- a/drivers/pwm/pwm-lpss.c
e336be
+++ b/drivers/pwm/pwm-lpss.c
e336be
@@ -159,8 +159,42 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
e336be
 	return 0;
e336be
 }
e336be
 
e336be
+/* This function gets called once from pwmchip_add to get the initial state */
e336be
+static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
e336be
+			       struct pwm_state *state)
e336be
+{
e336be
+	struct pwm_lpss_chip *lpwm = to_lpwm(chip);
e336be
+	unsigned long base_unit_range;
e336be
+	unsigned long long base_unit, freq, on_time_div;
e336be
+	u32 ctrl;
e336be
+
e336be
+	base_unit_range = BIT(lpwm->info->base_unit_bits);
e336be
+
e336be
+	ctrl = pwm_lpss_read(pwm);
e336be
+	on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK);
e336be
+	base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1);
e336be
+
e336be
+	freq = base_unit * lpwm->info->clk_rate;
e336be
+	do_div(freq, base_unit_range);
e336be
+	if (freq == 0)
e336be
+		state->period = NSEC_PER_SEC;
e336be
+	else
e336be
+		state->period = NSEC_PER_SEC / (unsigned long)freq;
e336be
+
e336be
+	on_time_div *= state->period;
e336be
+	do_div(on_time_div, 255);
e336be
+	state->duty_cycle = on_time_div;
e336be
+
e336be
+	state->polarity = PWM_POLARITY_NORMAL;
e336be
+	state->enabled = !!(ctrl & PWM_ENABLE);
e336be
+
e336be
+	if (state->enabled)
e336be
+		pm_runtime_get(chip->dev);
e336be
+}
e336be
+
e336be
 static const struct pwm_ops pwm_lpss_ops = {
e336be
 	.apply = pwm_lpss_apply,
e336be
+	.get_state = pwm_lpss_get_state,
e336be
 	.owner = THIS_MODULE,
e336be
 };
e336be
 
e336be
-- 
e336be
2.19.1
e336be
e336be
From e96509f196d1229cf66b19ad9f3d7cd43a86bc9d Mon Sep 17 00:00:00 2001
e336be
From: Hans de Goede <hdegoede@redhat.com>
e336be
Date: Sat, 13 Oct 2018 00:04:12 +0200
e336be
Subject: [PATCH 6/7] pwm: lpss: Force runtime-resume on suspend on Cherry
e336be
 Trail
e336be
e336be
On Cherry Trail devices under Windows the PWM controller used for the
e336be
backlight is considered part of the GPU even though it is part of the LPSS
e336be
block and thus is an entirely different independent hardware unit.
e336be
e336be
Because of this on Cherry Trail the GPU's (GFX0 ACPI node) _PS3 and _PS0
e336be
methods save and restore the PWM controller registers.
e336be
e336be
If userspace blanks the screen before suspending, such as e.g. GNOME
e336be
does, then the PWM controller will be runtime-suspended when the suspend
e336be
starts. This causes the GFX0 _PS? methods to save a value of 0xffffffff
e336be
for the PWM control register and to restore this value on resume.
e336be
e336be
0xffffffff is not a valid value for the register and writing this causes
e336be
problems such as e.g. a flickering backlight.
e336be
e336be
This commit adds a prepare method to the dev_pm_ops and makes it return 0
e336be
on Cherry Trail devices forcing a runtime-resume before other device's
e336be
suspend methods run. This fixes the reading and writing back of 0xffffffff.
e336be
e336be
Since we now always runtime-resume the device on suspend, it will be
e336be
resumed on resume too and we no longer need to check for the GFX0 _PS0
e336be
method having resumed it underneath us, so this commit removes the now no
e336be
longer necessary complete dev_pm_op.
e336be
e336be
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
e336be
---
e336be
 drivers/pwm/pwm-lpss-platform.c | 24 +++++++++++-------------
e336be
 drivers/pwm/pwm-lpss.h          |  7 +++++--
e336be
 2 files changed, 16 insertions(+), 15 deletions(-)
e336be
e336be
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
e336be
index b6edf8af26cc..757230e1f575 100644
e336be
--- a/drivers/pwm/pwm-lpss-platform.c
e336be
+++ b/drivers/pwm/pwm-lpss-platform.c
e336be
@@ -30,7 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
e336be
 	.clk_rate = 19200000,
e336be
 	.npwm = 1,
e336be
 	.base_unit_bits = 16,
e336be
-	.check_power_on_resume = true,
e336be
+	.other_devices_aml_touches_pwm_regs = true,
e336be
 };
e336be
 
e336be
 /* Broxton */
e336be
@@ -61,6 +61,7 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev)
e336be
 
e336be
 	platform_set_drvdata(pdev, lpwm);
e336be
 
e336be
+	dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);
e336be
 	pm_runtime_set_active(&pdev->dev);
e336be
 	pm_runtime_enable(&pdev->dev);
e336be
 
e336be
@@ -75,25 +76,22 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
e336be
 	return pwm_lpss_remove(lpwm);
e336be
 }
e336be
 
e336be
-static void pwm_lpss_complete(struct device *dev)
e336be
+static int pwm_lpss_prepare(struct device *dev)
e336be
 {
e336be
 	struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
e336be
-	int ret, state;
e336be
 
e336be
-	/* The PWM may be turned on by AML code, update our state to match */
e336be
-	if (pm_runtime_suspended(dev) && lpwm->info->check_power_on_resume) {
e336be
-		pm_runtime_disable(dev);
e336be
+	/*
e336be
+	 * If other device's AML code touches the PWM regs on suspend/resume
e336be
+	 * force runtime-resume the PWM controller to allow this.
e336be
+	 */
e336be
+	if (lpwm->info->other_devices_aml_touches_pwm_regs)
e336be
+		return 0; /* Force runtime-resume */
e336be
 
e336be
-		ret = acpi_device_get_power(ACPI_COMPANION(dev), &state);
e336be
-		if (ret == 0 && state == ACPI_STATE_D0)
e336be
-			pm_runtime_set_active(dev);
e336be
-
e336be
-		pm_runtime_enable(dev);
e336be
-	}
e336be
+	return 1; /* If runtime-suspended leave as is */
e336be
 }
e336be
 
e336be
 static const struct dev_pm_ops pwm_lpss_platform_pm_ops = {
e336be
-	.complete = pwm_lpss_complete,
e336be
+	.prepare = pwm_lpss_prepare,
e336be
 	SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume)
e336be
 };
e336be
 
e336be
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
e336be
index 1a2575d25bea..3236be835bd9 100644
e336be
--- a/drivers/pwm/pwm-lpss.h
e336be
+++ b/drivers/pwm/pwm-lpss.h
e336be
@@ -30,8 +30,11 @@ struct pwm_lpss_boardinfo {
e336be
 	unsigned int npwm;
e336be
 	unsigned long base_unit_bits;
e336be
 	bool bypass;
e336be
-	/* Some devices have AML code messing with the state underneath us */
e336be
-	bool check_power_on_resume;
e336be
+	/*
e336be
+	 * On some devices the _PS0/_PS3 AML code of the GPU (GFX0) device
e336be
+	 * messes with the PWM0 controllers state,
e336be
+	 */
e336be
+	bool other_devices_aml_touches_pwm_regs;
e336be
 };
e336be
 
e336be
 struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
e336be
-- 
e336be
2.19.1
e336be