]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/acpi/acpi_lpss.c
Merge tag 'fsnotify_for_v5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-jammy-kernel.git] / drivers / acpi / acpi_lpss.c
index 5e2bfbcf526f3d756bbad2c7545e025d48091c00..ca742f16a507a4d4b8634b813b52ff6156a111af 100644 (file)
@@ -26,8 +26,6 @@
 
 #include "internal.h"
 
-ACPI_MODULE_NAME("acpi_lpss");
-
 #ifdef CONFIG_X86_INTEL_LPSS
 
 #include <asm/cpu_device_id.h>
@@ -67,7 +65,15 @@ ACPI_MODULE_NAME("acpi_lpss");
 #define LPSS_CLK_DIVIDER               BIT(2)
 #define LPSS_LTR                       BIT(3)
 #define LPSS_SAVE_CTX                  BIT(4)
-#define LPSS_NO_D3_DELAY               BIT(5)
+/*
+ * For some devices the DSDT AML code for another device turns off the device
+ * before our suspend handler runs, causing us to read/save all 1-s (0xffffffff)
+ * as ctx register values.
+ * Luckily these devices always use the same ctx register values, so we can
+ * work around this by saving the ctx registers once on activation.
+ */
+#define LPSS_SAVE_CTX_ONCE             BIT(5)
+#define LPSS_NO_D3_DELAY               BIT(6)
 
 struct lpss_private_data;
 
@@ -254,9 +260,10 @@ static const struct lpss_device_desc byt_pwm_dev_desc = {
 };
 
 static const struct lpss_device_desc bsw_pwm_dev_desc = {
-       .flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
+       .flags = LPSS_SAVE_CTX_ONCE | LPSS_NO_D3_DELAY,
        .prv_offset = 0x800,
        .setup = bsw_pwm_setup,
+       .resume_from_noirq = true,
 };
 
 static const struct lpss_device_desc byt_uart_dev_desc = {
@@ -370,6 +377,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
 static int is_memory(struct acpi_resource *res, void *not_used)
 {
        struct resource r;
+
        return !acpi_dev_resource_memory(res, &r);
 }
 
@@ -884,9 +892,14 @@ static int acpi_lpss_activate(struct device *dev)
         * we have to deassert reset line to be sure that ->probe() will
         * recognize the device.
         */
-       if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
+       if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE))
                lpss_deassert_reset(pdata);
 
+#ifdef CONFIG_PM
+       if (pdata->dev_desc->flags & LPSS_SAVE_CTX_ONCE)
+               acpi_lpss_save_ctx(dev, pdata);
+#endif
+
        return 0;
 }
 
@@ -1030,7 +1043,7 @@ static int acpi_lpss_resume(struct device *dev)
 
        acpi_lpss_d3_to_d0_delay(pdata);
 
-       if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
+       if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE))
                acpi_lpss_restore_ctx(dev, pdata);
 
        return 0;
@@ -1188,6 +1201,7 @@ static int acpi_lpss_poweroff_noirq(struct device *dev)
        if (pdata->dev_desc->resume_from_noirq) {
                /* This is analogous to the acpi_lpss_suspend_noirq() case. */
                int ret = acpi_lpss_do_poweroff_late(dev);
+
                if (ret)
                        return ret;
        }