Extend the s2idle check with checking that none of the PMC clocks is in the forced on state. If one of the clocks is in forced on state then S0i3 cannot be reached. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- drivers/platform/x86/pmc_atom.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c index e14d489fa6f9..375010ef61ae 100644 --- a/drivers/platform/x86/pmc_atom.c +++ b/drivers/platform/x86/pmc_atom.c @@ -20,6 +20,14 @@ #include <linux/seq_file.h> #include <linux/suspend.h> +#define PMC_CLK_CTL_OFFSET 0x60 +#define PMC_CLK_NUM 6 +#define PMC_CLK_CTL_GATED_ON_D3 0x0 +#define PMC_CLK_CTL_FORCE_ON 0x1 +#define PMC_CLK_CTL_FORCE_OFF 0x2 +#define PMC_CLK_CTL_RESERVED 0x3 +#define PMC_MASK_CLK_CTL GENMASK(1, 0) + struct pmc_bit_map { const char *name; u32 bit_mask; @@ -477,6 +485,7 @@ static void pmc_s2idle_check(void) u32 func_dis, func_dis_2; u32 d3_sts_0, d3_sts_1; u32 false_pos_sts_0, false_pos_sts_1; + int i; func_dis = pmc_reg_read(pmc, PMC_FUNC_DIS); func_dis_2 = pmc_reg_read(pmc, PMC_FUNC_DIS_2); @@ -504,6 +513,16 @@ static void pmc_s2idle_check(void) /* High part */ pmc_dev_state_check(d3_sts_1, m->d3_sts_1, func_dis_2, m->func_dis_2, false_pos_sts_1); + + /* Check PMC clocks */ + for (i = 0; i < PMC_CLK_NUM; i++) { + u32 ctl = pmc_reg_read(pmc, PMC_CLK_CTL_OFFSET + 4 * i); + + if ((ctl & PMC_MASK_CLK_CTL) != PMC_CLK_CTL_FORCE_ON) + continue; + + pr_err("pmc_atom: clk %d is ON prior to freeze (ctl %08x)\n", i, ctl); + } } static struct acpi_s2idle_dev_ops pmc_s2idle_ops = { -- 2.43.0