diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index b9f34e492a24..f2c621b55f49 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -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; }; /**