mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 21:53:44 +00:00
HID: intel-ish-hid: ipc: finish power flow for EHL OOB
The EHL (Elkhart Lake) based platforms provide a OOB (Out of band) service, which allows wakup device when the system is in S5 (Soft-Off state). This OOB service can be enabled/disabled from BIOS settings. When enabled, the ISH device gets PME wake capability. To enable PME wakeup, driver also needs to enable ACPI GPE bit. Once wakeup, BIOS will clear the wakeup bit to identify wakeup is successful. So driver need to re-enable it in resume function to keep the next wakeup capability. Since this feature is only present on EHL, we use EHL PCI device id to enable this feature. Co-developed-by: Najumon Ba <najumon.ba@intel.com> Signed-off-by: Najumon Ba <najumon.ba@intel.com> Signed-off-by: Even Xu <even.xu@intel.com> Signed-off-by: Zhang Lixu <lixu.zhang@intel.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
de925e2fbb
commit
2e23a70eda
@ -5,6 +5,7 @@
|
||||
* Copyright (c) 2014-2016, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -111,6 +112,42 @@ static inline bool ish_should_leave_d0i3(struct pci_dev *pdev)
|
||||
return !pm_resume_via_firmware() || pdev->device == CHV_DEVICE_ID;
|
||||
}
|
||||
|
||||
static int enable_gpe(struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
acpi_status acpi_sts;
|
||||
struct acpi_device *adev;
|
||||
struct acpi_device_wakeup *wakeup;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (!adev) {
|
||||
dev_err(dev, "get acpi handle failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
wakeup = &adev->wakeup;
|
||||
|
||||
acpi_sts = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
|
||||
if (ACPI_FAILURE(acpi_sts)) {
|
||||
dev_err(dev, "enable ose_gpe failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -ENODEV;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void enable_pme_wake(struct pci_dev *pdev)
|
||||
{
|
||||
if ((pci_pme_capable(pdev, PCI_D0) ||
|
||||
pci_pme_capable(pdev, PCI_D3hot) ||
|
||||
pci_pme_capable(pdev, PCI_D3cold)) && !enable_gpe(&pdev->dev)) {
|
||||
pci_pme_active(pdev, true);
|
||||
dev_dbg(&pdev->dev, "ish ipc driver pme wake enabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ish_probe() - PCI driver probe callback
|
||||
* @pdev: pci device
|
||||
@ -179,6 +216,10 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
init_waitqueue_head(&ishtp->suspend_wait);
|
||||
init_waitqueue_head(&ishtp->resume_wait);
|
||||
|
||||
/* Enable PME for EHL */
|
||||
if (pdev->device == EHL_Ax_DEVICE_ID)
|
||||
enable_pme_wake(pdev);
|
||||
|
||||
ret = ish_init(ishtp);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -317,6 +358,13 @@ static int __maybe_unused ish_resume(struct device *device)
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct ishtp_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
/* add this to finish power flow for EHL */
|
||||
if (dev->pdev->device == EHL_Ax_DEVICE_ID) {
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
enable_pme_wake(pdev);
|
||||
dev_dbg(dev->devc, "set power state to D0 for ehl\n");
|
||||
}
|
||||
|
||||
ish_resume_device = device;
|
||||
dev->resume_flag = 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user