From: Xi Pardee Date: Thu, 8 Jan 2026 22:31:40 +0000 (-0800) Subject: platform/x86/intel/pmc: Move LPM mode attributes to PMC X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=92911c91b5b7049cb634ef912feab086fd54ed43;p=thirdparty%2Flinux.git platform/x86/intel/pmc: Move LPM mode attributes to PMC Move LPM modes attributes from the pmc_dev to the pmc structure. LPM modes are PMC-specific and should be stored within the pmc structure. After the change, LPM mode information will be retrieved and stored per PMC. The substate_requirements attribute in debugfs will display the requirements for each enabled LPM substate. Signed-off-by: Xi Pardee Link: https://patch.msgid.link/20260108223144.504267-3-xi.pardee@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index c55149f226671..c76934ad7bf1d 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -783,7 +783,7 @@ static int pmc_core_substate_res_show(struct seq_file *s, void *unused) seq_printf(s, "%-10s %-15s\n", "Substate", "Residency"); - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { seq_printf(s, "%-10s %-15llu\n", pmc_lpm_modes[mode], adjust_lpm_residency(pmc, offset + (4 * mode), lpm_adj_x2)); } @@ -838,10 +838,11 @@ static void pmc_core_substate_req_header_show(struct seq_file *s, int pmc_index, enum header_type type) { struct pmc_dev *pmcdev = s->private; + struct pmc *pmc = pmcdev->pmcs[pmc_index]; u8 mode; seq_printf(s, "%40s |", "Element"); - pmc_for_each_mode(mode, pmcdev) + pmc_for_each_mode(mode, pmc) seq_printf(s, " %9s |", pmc_lpm_modes[mode]); if (type == HEADER_STATUS) { @@ -887,7 +888,7 @@ static int pmc_core_substate_blk_req_show(struct seq_file *s, void *unused) counter = pmc_core_reg_read(pmc, offset); seq_printf(s, "pmc%u: %34s |", pmc_idx, map->name); - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { bool required = *lpm_req_regs & BIT(mode); seq_printf(s, " %9s |", required ? "Required" : " "); @@ -961,7 +962,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) * show an element if it's required for at least one of the * enabled low power modes */ - pmc_for_each_mode(mode, pmcdev) + pmc_for_each_mode(mode, pmc) req_mask |= lpm_req_regs[mp + (mode * num_maps)]; /* Get the last latched status for this map */ @@ -987,7 +988,7 @@ static int pmc_core_substate_req_regs_show(struct seq_file *s, void *unused) seq_printf(s, "pmc%d: %34s |", pmc_idx, map[i].name); /* Loop over the enabled states and display if required */ - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { bool required = lpm_req_regs[mp + (mode * num_maps)] & bit_mask; seq_printf(s, " %9s |", required ? "Required" : " "); @@ -1077,7 +1078,7 @@ static int pmc_core_lpm_latch_mode_show(struct seq_file *s, void *unused) c10 = true; } - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { if ((BIT(mode) & reg) && !c10) seq_printf(s, " [%s]", pmc_lpm_modes[mode]); else @@ -1117,7 +1118,7 @@ static ssize_t pmc_core_lpm_latch_mode_write(struct file *file, mode = sysfs_match_string(pmc_lpm_modes, buf); /* Check string matches enabled mode */ - pmc_for_each_mode(m, pmcdev) + pmc_for_each_mode(m, pmc) if (mode == m) break; @@ -1213,9 +1214,8 @@ static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order) return true; } -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) +static void pmc_core_pmc_get_low_power_modes(struct pmc_dev *pmcdev, struct pmc *pmc) { - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI; u8 mode_order[LPM_MAX_NUM_MODES]; u32 lpm_pri; @@ -1233,7 +1233,7 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) * Lower byte is enough to cover the number of lpm modes for all * platforms and hence mask the upper 3 bytes. */ - pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF); + pmc->num_lpm_modes = hweight32(lpm_en & 0xFF); /* Read 32 bit LPM_PRI register */ lpm_pri = pmc_core_reg_read(pmc, pmc->map->lpm_priority_offset); @@ -1262,7 +1262,22 @@ void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) if (!(BIT(mode) & lpm_en)) continue; - pmcdev->lpm_en_modes[i++] = mode; + pmc->lpm_en_modes[i++] = mode; + } +} + +static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev) +{ + unsigned int pmc_idx; + + for (pmc_idx = 0; pmc_idx < ARRAY_SIZE(pmcdev->pmcs); pmc_idx++) { + struct pmc *pmc; + + pmc = pmcdev->pmcs[pmc_idx]; + if (!pmc) + continue; + + pmc_core_pmc_get_low_power_modes(pmcdev, pmc); } } @@ -1507,7 +1522,7 @@ int pmc_core_pmt_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, struct tel return -ENOMEM; mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; - pmc_for_each_mode(mode, pmcdev) { + pmc_for_each_mode(mode, pmc) { u32 *req_offset = pmc->lpm_req_regs + (mode * num_maps); int m; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index ead2f33ed3ed5..118c8740ad3aa 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -423,6 +423,8 @@ struct pmc_info { * specific attributes * @lpm_req_regs: List of substate requirements * @ltr_ign: Holds LTR ignore data while suspended + * @num_lpm_modes: Count of enabled modes + * @lpm_en_modes: Array of enabled modes from lowest to highest priority * * pmc contains info about one power management controller device. */ @@ -432,6 +434,8 @@ struct pmc { const struct pmc_reg_map *map; u32 *lpm_req_regs; u32 ltr_ign; + u8 num_lpm_modes; + u8 lpm_en_modes[LPM_MAX_NUM_MODES]; }; /** @@ -446,8 +450,6 @@ struct pmc { * @pkgc_res_cnt: Array of PKGC residency counters * @num_of_pkgc: Number of PKGC * @s0ix_counter: S0ix residency (step adjusted) - * @num_lpm_modes: Count of enabled modes - * @lpm_en_modes: Array of enabled modes from lowest to highest priority * @suspend: Function to perform platform specific suspend * @resume: Function to perform platform specific resume * @@ -462,8 +464,6 @@ struct pmc_dev { struct mutex lock; /* generic mutex lock for PMC Core */ u64 s0ix_counter; - u8 num_lpm_modes; - u8 lpm_en_modes[LPM_MAX_NUM_MODES]; void (*suspend)(struct pmc_dev *pmcdev); int (*resume)(struct pmc_dev *pmcdev); @@ -535,7 +535,6 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); int pmc_core_resume_common(struct pmc_dev *pmcdev); int get_primary_reg_base(struct pmc *pmc); -void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev); void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 *guids); void pmc_core_set_device_d3(unsigned int device); @@ -563,10 +562,10 @@ int pmc_core_pmt_get_blk_sub_req(struct pmc_dev *pmcdev, struct pmc *pmc, extern const struct file_operations pmc_core_substate_req_regs_fops; extern const struct file_operations pmc_core_substate_blk_req_fops; -#define pmc_for_each_mode(mode, pmcdev) \ +#define pmc_for_each_mode(mode, pmc) \ for (unsigned int __i = 0, __cond; \ - __cond = __i < (pmcdev)->num_lpm_modes, \ - __cond && ((mode) = (pmcdev)->lpm_en_modes[__i]), \ + __cond = __i < (pmc)->num_lpm_modes, \ + __cond && ((mode) = (pmc)->lpm_en_modes[__i]), \ __cond; \ __i++)