Link: https://bit.ly/2UmnrFf
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=201579
Tested-by: "David E. Box" <david.e.box@xxxxxxxxxxxxxxx>
Reported-and-tested-by: russianneuromancer <russianneuromancer@xxxxx>
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@xxxxxxxxxxxxxxx>
---
drivers/platform/x86/intel_pmc_core.c | 34 +++++++++++++++++++++++++++
drivers/platform/x86/intel_pmc_core.h | 5 ++++
2 files changed, 39 insertions(+)
diff --git a/drivers/platform/x86/intel_pmc_core.c
b/drivers/platform/x86/intel_pmc_core.c
index 4e7aa1711148..a27574e3e868 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -15,6 +15,7 @@
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -151,6 +152,7 @@ static const struct pmc_reg_map spt_reg_map = {
.pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED,
+ .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,
};
/* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */
@@ -821,6 +823,37 @@ static const struct pci_device_id pmc_pci_ids[] = {
{ 0, },
};
+/*
+ * This quirk can be used on those platforms where
+ * the platform BIOS enforces 24Mhx Crystal to shutdown
+ * before PMC can assert SLP_S0#.
+ */
+int quirk_xtal_ignore(const struct dmi_system_id *id)
+{
+ struct pmc_dev *pmcdev = &pmc;
+ u32 value;
+
+ value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset);
+ /* 24MHz Crystal Shutdown Qualification Disable */
+ value |= SPT_PMC_VRIC1_XTALSDQDIS;
+ /* Low Voltage Mode Enable */
+ value &= ~SPT_PMC_VRIC1_SLPS0LVEN;
+ pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value);
+ return 0;
+}
+
+static const struct dmi_system_id pmc_core_dmi_table[] = {
+ {
+ .callback = quirk_xtal_ignore,
+ .ident = "HP Elite x2 1013 G3",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite x2 1013 G3"),
+ },
+ },
+ {}
+};
+
static int __init pmc_core_probe(void)
{
struct pmc_dev *pmcdev = &pmc;
@@ -862,6 +895,7 @@ static int __init pmc_core_probe(void)
return err;
}
+ dmi_check_system(pmc_core_dmi_table);
pr_info(" initialized\n");
return 0;
}
diff --git a/drivers/platform/x86/intel_pmc_core.h
b/drivers/platform/x86/intel_pmc_core.h
index 6f1b64808075..88d9c0653a5f 100644
--- a/drivers/platform/x86/intel_pmc_core.h
+++ b/drivers/platform/x86/intel_pmc_core.h
@@ -25,6 +25,7 @@
#define SPT_PMC_MTPMC_OFFSET 0x20
#define SPT_PMC_MFPMC_OFFSET 0x38
#define SPT_PMC_LTR_IGNORE_OFFSET 0x30C
+#define SPT_PMC_VRIC1_OFFSET 0x31c
#define SPT_PMC_MPHY_CORE_STS_0 0x1143
#define SPT_PMC_MPHY_CORE_STS_1 0x1142
#define SPT_PMC_MPHY_COM_STS_0 0x1155
@@ -136,6 +137,9 @@ enum ppfear_regs {
#define SPT_PMC_BIT_MPHY_CMN_LANE2 BIT(2)
#define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3)
+#define SPT_PMC_VRIC1_SLPS0LVEN BIT(13)
+#define SPT_PMC_VRIC1_XTALSDQDIS BIT(22)
+
/* Cannonlake Power Management Controller register offsets */
#define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4
#define CNP_PMC_PM_CFG_OFFSET 0x1818
@@ -224,6 +228,7 @@ struct pmc_reg_map {
const int pm_read_disable_bit;
const u32 slps0_dbg_offset;
const u32 ltr_ignore_max;
+ const u32 pm_vric1_offset;
};
/**
--
2.17.1