Skip to content

Commit e86c818

Browse files
MaslankaMarekdlezcano
authored andcommitted
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 <[email protected]> Reviewed-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Daniel Lezcano <[email protected]>
1 parent 56bd72e commit e86c818

File tree

8 files changed

+65
-0
lines changed

8 files changed

+65
-0
lines changed

drivers/platform/x86/intel/pmc/adl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ const struct pmc_reg_map adl_reg_map = {
295295
.ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES,
296296
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
297297
.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,
298300
.ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
299301
.lpm_num_modes = ADL_LPM_NUM_MODES,
300302
.lpm_num_maps = ADL_LPM_NUM_MAPS,

drivers/platform/x86/intel/pmc/cnp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ const struct pmc_reg_map cnp_reg_map = {
200200
.ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES,
201201
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
202202
.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,
203205
.ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED,
204206
.etr3_offset = ETR3_OFFSET,
205207
};

drivers/platform/x86/intel/pmc/core.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1313

14+
#include <linux/acpi_pmtmr.h>
1415
#include <linux/bitfield.h>
1516
#include <linux/debugfs.h>
1617
#include <linux/delay.h>
@@ -1208,6 +1209,38 @@ static bool pmc_core_is_pson_residency_enabled(struct pmc_dev *pmcdev)
12081209
return val == 1;
12091210
}
12101211

1212+
/**
1213+
* Enable or disable ACPI PM Timer
1214+
*
1215+
* This function is intended to be a callback for ACPI PM suspend/resume event.
1216+
* The ACPI PM Timer is enabled on resume only if it was enabled during suspend.
1217+
*/
1218+
static void pmc_core_acpi_pm_timer_suspend_resume(void *data, bool suspend)
1219+
{
1220+
struct pmc_dev *pmcdev = data;
1221+
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
1222+
const struct pmc_reg_map *map = pmc->map;
1223+
bool enabled;
1224+
u32 reg;
1225+
1226+
if (!map->acpi_pm_tmr_ctl_offset)
1227+
return;
1228+
1229+
guard(mutex)(&pmcdev->lock);
1230+
1231+
if (!suspend && !pmcdev->enable_acpi_pm_timer_on_resume)
1232+
return;
1233+
1234+
reg = pmc_core_reg_read(pmc, map->acpi_pm_tmr_ctl_offset);
1235+
enabled = !(reg & map->acpi_pm_tmr_disable_bit);
1236+
if (suspend)
1237+
reg |= map->acpi_pm_tmr_disable_bit;
1238+
else
1239+
reg &= ~map->acpi_pm_tmr_disable_bit;
1240+
pmc_core_reg_write(pmc, map->acpi_pm_tmr_ctl_offset, reg);
1241+
1242+
pmcdev->enable_acpi_pm_timer_on_resume = suspend && enabled;
1243+
}
12111244

12121245
static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
12131246
{
@@ -1404,6 +1437,7 @@ static int pmc_core_probe(struct platform_device *pdev)
14041437
struct pmc_dev *pmcdev;
14051438
const struct x86_cpu_id *cpu_id;
14061439
int (*core_init)(struct pmc_dev *pmcdev);
1440+
const struct pmc_reg_map *map;
14071441
struct pmc *primary_pmc;
14081442
int ret;
14091443

@@ -1462,6 +1496,11 @@ static int pmc_core_probe(struct platform_device *pdev)
14621496
pm_report_max_hw_sleep(FIELD_MAX(SLP_S0_RES_COUNTER_MASK) *
14631497
pmc_core_adjust_slp_s0_step(primary_pmc, 1));
14641498

1499+
map = primary_pmc->map;
1500+
if (map->acpi_pm_tmr_ctl_offset)
1501+
acpi_pmtmr_register_suspend_resume_callback(pmc_core_acpi_pm_timer_suspend_resume,
1502+
pmcdev);
1503+
14651504
device_initialized = true;
14661505
dev_info(&pdev->dev, " initialized\n");
14671506

@@ -1471,6 +1510,12 @@ static int pmc_core_probe(struct platform_device *pdev)
14711510
static void pmc_core_remove(struct platform_device *pdev)
14721511
{
14731512
struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
1513+
const struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
1514+
const struct pmc_reg_map *map = pmc->map;
1515+
1516+
if (map->acpi_pm_tmr_ctl_offset)
1517+
acpi_pmtmr_unregister_suspend_resume_callback();
1518+
14741519
pmc_core_dbgfs_unregister(pmcdev);
14751520
pmc_core_clean_structure(pdev);
14761521
}

drivers/platform/x86/intel/pmc/core.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct telem_endpoint;
6868
#define SPT_PMC_LTR_SCC 0x3A0
6969
#define SPT_PMC_LTR_ISH 0x3A4
7070

71+
#define SPT_PMC_ACPI_PM_TMR_CTL_OFFSET 0x18FC
72+
7173
/* Sunrise Point: PGD PFET Enable Ack Status Registers */
7274
enum ppfear_regs {
7375
SPT_PMC_XRAM_PPFEAR0A = 0x590,
@@ -148,6 +150,8 @@ enum ppfear_regs {
148150
#define SPT_PMC_VRIC1_SLPS0LVEN BIT(13)
149151
#define SPT_PMC_VRIC1_XTALSDQDIS BIT(22)
150152

153+
#define SPT_PMC_BIT_ACPI_PM_TMR_DISABLE BIT(1)
154+
151155
/* Cannonlake Power Management Controller register offsets */
152156
#define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4
153157
#define CNP_PMC_PM_CFG_OFFSET 0x1818
@@ -351,6 +355,8 @@ struct pmc_reg_map {
351355
const u8 *lpm_reg_index;
352356
const u32 pson_residency_offset;
353357
const u32 pson_residency_counter_step;
358+
const u32 acpi_pm_tmr_ctl_offset;
359+
const u32 acpi_pm_tmr_disable_bit;
354360
};
355361

356362
/**
@@ -424,6 +430,8 @@ struct pmc_dev {
424430
u32 die_c6_offset;
425431
struct telem_endpoint *punit_ep;
426432
struct pmc_info *regmap_list;
433+
434+
bool enable_acpi_pm_timer_on_resume;
427435
};
428436

429437
enum pmc_index {

drivers/platform/x86/intel/pmc/icl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const struct pmc_reg_map icl_reg_map = {
4646
.ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES,
4747
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
4848
.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,
4951
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
5052
.etr3_offset = ETR3_OFFSET,
5153
};

drivers/platform/x86/intel/pmc/mtl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ const struct pmc_reg_map mtl_socm_reg_map = {
462462
.ppfear_buckets = MTL_SOCM_PPFEAR_NUM_ENTRIES,
463463
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
464464
.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,
465467
.lpm_num_maps = ADL_LPM_NUM_MAPS,
466468
.ltr_ignore_max = MTL_SOCM_NUM_IP_IGN_ALLOWED,
467469
.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,

drivers/platform/x86/intel/pmc/spt.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ const struct pmc_reg_map spt_reg_map = {
130130
.ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES,
131131
.pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET,
132132
.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,
133135
.ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED,
134136
.pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,
135137
};

drivers/platform/x86/intel/pmc/tgl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ const struct pmc_reg_map tgl_reg_map = {
197197
.ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES,
198198
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
199199
.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,
200202
.ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED,
201203
.lpm_num_maps = TGL_LPM_NUM_MAPS,
202204
.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,

0 commit comments

Comments
 (0)