Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

platform/x86:intel/pmc: Enable the ACPI PM Timer to be turned off when suspended

Allow to disable ACPI PM Timer on suspend and enable on resume. A
disabled timer helps optimise power consumption when the system is
suspended. On resume the timer is only reactivated if it was activated
prior to suspend, so unless the ACPI PM timer is enabled in the BIOS,
this won't change anything.

The ACPI PM timer is used by Intel's iTCO/wdat_wdt watchdog to drive the
watchdog, so it doesn't need to run during suspend.

Signed-off-by: Marek Maslanka <mmaslanka@google.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20240812184208.1080710-1-mmaslanka@google.com
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>

authored by

Marek Maslanka and committed by
Daniel Lezcano
e86c8186 56bd72e9

+65
+2
drivers/platform/x86/intel/pmc/adl.c
··· 295 295 .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, 296 296 .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, 297 297 .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, 298 + .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, 299 + .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, 298 300 .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, 299 301 .lpm_num_modes = ADL_LPM_NUM_MODES, 300 302 .lpm_num_maps = ADL_LPM_NUM_MAPS,
+2
drivers/platform/x86/intel/pmc/cnp.c
··· 200 200 .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, 201 201 .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, 202 202 .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, 203 + .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, 204 + .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, 203 205 .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, 204 206 .etr3_offset = ETR3_OFFSET, 205 207 };
+45
drivers/platform/x86/intel/pmc/core.c
··· 11 11 12 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 13 14 + #include <linux/acpi_pmtmr.h> 14 15 #include <linux/bitfield.h> 15 16 #include <linux/debugfs.h> 16 17 #include <linux/delay.h> ··· 1209 1208 return val == 1; 1210 1209 } 1211 1210 1211 + /** 1212 + * Enable or disable ACPI PM Timer 1213 + * 1214 + * This function is intended to be a callback for ACPI PM suspend/resume event. 1215 + * The ACPI PM Timer is enabled on resume only if it was enabled during suspend. 1216 + */ 1217 + static void pmc_core_acpi_pm_timer_suspend_resume(void *data, bool suspend) 1218 + { 1219 + struct pmc_dev *pmcdev = data; 1220 + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 1221 + const struct pmc_reg_map *map = pmc->map; 1222 + bool enabled; 1223 + u32 reg; 1224 + 1225 + if (!map->acpi_pm_tmr_ctl_offset) 1226 + return; 1227 + 1228 + guard(mutex)(&pmcdev->lock); 1229 + 1230 + if (!suspend && !pmcdev->enable_acpi_pm_timer_on_resume) 1231 + return; 1232 + 1233 + reg = pmc_core_reg_read(pmc, map->acpi_pm_tmr_ctl_offset); 1234 + enabled = !(reg & map->acpi_pm_tmr_disable_bit); 1235 + if (suspend) 1236 + reg |= map->acpi_pm_tmr_disable_bit; 1237 + else 1238 + reg &= ~map->acpi_pm_tmr_disable_bit; 1239 + pmc_core_reg_write(pmc, map->acpi_pm_tmr_ctl_offset, reg); 1240 + 1241 + pmcdev->enable_acpi_pm_timer_on_resume = suspend && enabled; 1242 + } 1212 1243 1213 1244 static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) 1214 1245 { ··· 1437 1404 struct pmc_dev *pmcdev; 1438 1405 const struct x86_cpu_id *cpu_id; 1439 1406 int (*core_init)(struct pmc_dev *pmcdev); 1407 + const struct pmc_reg_map *map; 1440 1408 struct pmc *primary_pmc; 1441 1409 int ret; 1442 1410 ··· 1496 1462 pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) * 1497 1463 pmc_core_adjust_slp_s0_step(primary_pmc, 1)); 1498 1464 1465 + map = primary_pmc->map; 1466 + if (map->acpi_pm_tmr_ctl_offset) 1467 + acpi_pmtmr_register_suspend_resume_callback(pmc_core_acpi_pm_timer_suspend_resume, 1468 + pmcdev); 1469 + 1499 1470 device_initialized = true; 1500 1471 dev_info(&pdev->dev, " initialized\n"); 1501 1472 ··· 1510 1471 static void pmc_core_remove(struct platform_device *pdev) 1511 1472 { 1512 1473 struct pmc_dev *pmcdev = platform_get_drvdata(pdev); 1474 + const struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; 1475 + const struct pmc_reg_map *map = pmc->map; 1476 + 1477 + if (map->acpi_pm_tmr_ctl_offset) 1478 + acpi_pmtmr_unregister_suspend_resume_callback(); 1479 + 1513 1480 pmc_core_dbgfs_unregister(pmcdev); 1514 1481 pmc_core_clean_structure(pdev); 1515 1482 }
+8
drivers/platform/x86/intel/pmc/core.h
··· 68 68 #define SPT_PMC_LTR_SCC 0x3A0 69 69 #define SPT_PMC_LTR_ISH 0x3A4 70 70 71 + #define SPT_PMC_ACPI_PM_TMR_CTL_OFFSET 0x18FC 72 + 71 73 /* Sunrise Point: PGD PFET Enable Ack Status Registers */ 72 74 enum ppfear_regs { 73 75 SPT_PMC_XRAM_PPFEAR0A = 0x590, ··· 149 147 150 148 #define SPT_PMC_VRIC1_SLPS0LVEN BIT(13) 151 149 #define SPT_PMC_VRIC1_XTALSDQDIS BIT(22) 150 + 151 + #define SPT_PMC_BIT_ACPI_PM_TMR_DISABLE BIT(1) 152 152 153 153 /* Cannonlake Power Management Controller register offsets */ 154 154 #define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4 ··· 355 351 const u8 *lpm_reg_index; 356 352 const u32 pson_residency_offset; 357 353 const u32 pson_residency_counter_step; 354 + const u32 acpi_pm_tmr_ctl_offset; 355 + const u32 acpi_pm_tmr_disable_bit; 358 356 }; 359 357 360 358 /** ··· 430 424 u32 die_c6_offset; 431 425 struct telem_endpoint *punit_ep; 432 426 struct pmc_info *regmap_list; 427 + 428 + bool enable_acpi_pm_timer_on_resume; 433 429 }; 434 430 435 431 enum pmc_index {
+2
drivers/platform/x86/intel/pmc/icl.c
··· 46 46 .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, 47 47 .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, 48 48 .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, 49 + .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, 50 + .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, 49 51 .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, 50 52 .etr3_offset = ETR3_OFFSET, 51 53 };
+2
drivers/platform/x86/intel/pmc/mtl.c
··· 462 462 .ppfear_buckets = MTL_SOCM_PPFEAR_NUM_ENTRIES, 463 463 .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, 464 464 .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, 465 + .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, 466 + .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, 465 467 .lpm_num_maps = ADL_LPM_NUM_MAPS, 466 468 .ltr_ignore_max = MTL_SOCM_NUM_IP_IGN_ALLOWED, 467 469 .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
+2
drivers/platform/x86/intel/pmc/spt.c
··· 130 130 .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, 131 131 .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, 132 132 .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, 133 + .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, 134 + .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, 133 135 .ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED, 134 136 .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET, 135 137 };
+2
drivers/platform/x86/intel/pmc/tgl.c
··· 197 197 .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, 198 198 .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, 199 199 .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, 200 + .acpi_pm_tmr_ctl_offset = SPT_PMC_ACPI_PM_TMR_CTL_OFFSET, 201 + .acpi_pm_tmr_disable_bit = SPT_PMC_BIT_ACPI_PM_TMR_DISABLE, 200 202 .ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED, 201 203 .lpm_num_maps = TGL_LPM_NUM_MAPS, 202 204 .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,