On Wed, 28 Aug 2024, Xi Pardee wrote: > Move functions that implements PMC Core feature from core_ssram.c > to core.c. This patch is a preparation step to introduce a new > SSRAM Telemetry driver for the SSRAM device. > > Signed-off-by: Xi Pardee <xi.pardee@xxxxxxxxxxxxxxx> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx> > --- > drivers/platform/x86/intel/pmc/core.c | 168 +++++++++++++++++++ > drivers/platform/x86/intel/pmc/core.h | 8 + > drivers/platform/x86/intel/pmc/core_ssram.c | 173 -------------------- > 3 files changed, 176 insertions(+), 173 deletions(-) > > diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c > index 01ae71c6df59..630ce2087552 100644 > --- a/drivers/platform/x86/intel/pmc/core.c > +++ b/drivers/platform/x86/intel/pmc/core.c > @@ -1604,6 +1604,173 @@ static const struct dev_pm_ops pmc_core_pm_ops = { > SET_LATE_SYSTEM_SLEEP_PM_OPS(pmc_core_suspend, pmc_core_resume) > }; > > +static u32 pmc_core_find_guid(struct pmc_info *list, const struct pmc_reg_map *map) > +{ > + for (; list->map; ++list) > + if (list->map == map) > + return list->guid; > + > + return 0; > +} > + > +static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc) > +{ > + struct telem_endpoint *ep; > + const u8 *lpm_indices; > + int num_maps, mode_offset = 0; > + int ret, mode, i; > + int lpm_size; > + u32 guid; > + > + lpm_indices = pmc->map->lpm_reg_index; > + num_maps = pmc->map->lpm_num_maps; > + lpm_size = LPM_MAX_NUM_MODES * num_maps; > + > + guid = pmc_core_find_guid(pmcdev->regmap_list, pmc->map); > + if (!guid) > + return -ENXIO; > + > + ep = pmt_telem_find_and_register_endpoint(pmcdev->ssram_pcidev, guid, 0); > + if (IS_ERR(ep)) { > + dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %ld", > + PTR_ERR(ep)); > + return -EPROBE_DEFER; > + } > + > + pmc->lpm_req_regs = devm_kzalloc(&pmcdev->pdev->dev, > + lpm_size * sizeof(u32), > + GFP_KERNEL); > + if (!pmc->lpm_req_regs) { > + ret = -ENOMEM; > + goto unregister_ep; > + } > + > + /* > + * PMC Low Power Mode (LPM) table > + * > + * In telemetry space, the LPM table contains a 4 byte header followed > + * by 8 consecutive mode blocks (one for each LPM mode). Each block > + * has a 4 byte header followed by a set of registers that describe the > + * IP state requirements for the given mode. The IP mapping is platform > + * specific but the same for each block, making for easy analysis. > + * Platforms only use a subset of the space to track the requirements > + * for their IPs. Callers provide the requirement registers they use as > + * a list of indices. Each requirement register is associated with an > + * IP map that's maintained by the caller. > + * > + * Header > + * +----+----------------------------+----------------------------+ > + * | 0 | REVISION | ENABLED MODES | > + * +----+--------------+-------------+-------------+--------------+ > + * > + * Low Power Mode 0 Block > + * +----+--------------+-------------+-------------+--------------+ > + * | 1 | SUB ID | SIZE | MAJOR | MINOR | > + * +----+--------------+-------------+-------------+--------------+ > + * | 2 | LPM0 Requirements 0 | > + * +----+---------------------------------------------------------+ > + * | | ... | > + * +----+---------------------------------------------------------+ > + * | 29 | LPM0 Requirements 27 | > + * +----+---------------------------------------------------------+ > + * > + * ... > + * > + * Low Power Mode 7 Block > + * +----+--------------+-------------+-------------+--------------+ > + * | | SUB ID | SIZE | MAJOR | MINOR | > + * +----+--------------+-------------+-------------+--------------+ > + * | 60 | LPM7 Requirements 0 | > + * +----+---------------------------------------------------------+ > + * | | ... | > + * +----+---------------------------------------------------------+ > + * | 87 | LPM7 Requirements 27 | > + * +----+---------------------------------------------------------+ > + * > + */ > + mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; > + pmc_for_each_mode(i, mode, pmcdev) { > + u32 *req_offset = pmc->lpm_req_regs + (mode * num_maps); > + int m; > + > + for (m = 0; m < num_maps; m++) { > + u8 sample_id = lpm_indices[m] + mode_offset; > + > + ret = pmt_telem_read32(ep, sample_id, req_offset, 1); > + if (ret) { > + dev_err(&pmcdev->pdev->dev, > + "couldn't read Low Power Mode requirements: %d\n", ret); > + devm_kfree(&pmcdev->pdev->dev, pmc->lpm_req_regs); > + goto unregister_ep; > + } > + ++req_offset; > + } > + mode_offset += LPM_REG_COUNT + LPM_MODE_OFFSET; > + } > + > +unregister_ep: > + pmt_telem_unregister_endpoint(ep); > + > + return ret; > +} > + > +int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev) > +{ > + int ret, i; > + > + if (!pmcdev->ssram_pcidev) > + return -ENODEV; > + > + for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { > + if (!pmcdev->pmcs[i]) > + continue; > + > + ret = pmc_core_get_lpm_req(pmcdev, pmcdev->pmcs[i]); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid) > +{ > + for (; list->map; ++list) > + if (devid == list->devid) > + return list->map; > + > + return NULL; > +} > + > +int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base, > + const struct pmc_reg_map *reg_map, int pmc_index) > +{ > + struct pmc *pmc = pmcdev->pmcs[pmc_index]; > + > + if (!pwrm_base) > + return -ENODEV; > + > + /* Memory for primary PMC has been allocated in core.c */ > + if (!pmc) { > + pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL); > + if (!pmc) > + return -ENOMEM; > + } > + > + pmc->map = reg_map; > + pmc->base_addr = pwrm_base; > + pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); > + > + if (!pmc->regbase) { > + devm_kfree(&pmcdev->pdev->dev, pmc); > + return -ENOMEM; > + } > + > + pmcdev->pmcs[pmc_index] = pmc; > + > + return 0; > +} > + > static const struct acpi_device_id pmc_core_acpi_ids[] = { > {"INT33A1", 0}, /* _HID for Intel Power Engine, _CID PNP0D80*/ > { } > @@ -1623,5 +1790,6 @@ static struct platform_driver pmc_core_driver = { > > module_platform_driver(pmc_core_driver); > > +MODULE_IMPORT_NS(INTEL_PMT_TELEMETRY); > MODULE_LICENSE("GPL v2"); > MODULE_DESCRIPTION("Intel PMC Core Driver"); > diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h > index ea04de7eb9e8..9a1cc01f31d9 100644 > --- a/drivers/platform/x86/intel/pmc/core.h > +++ b/drivers/platform/x86/intel/pmc/core.h > @@ -24,6 +24,11 @@ struct telem_endpoint; > #define MAX_NUM_PMC 3 > #define S0IX_BLK_SIZE 4 > > +/* PCH query */ > +#define LPM_HEADER_OFFSET 1 > +#define LPM_REG_COUNT 28 > +#define LPM_MODE_OFFSET 1 > + > /* Sunrise Point Power Management Controller PCI Device ID */ > #define SPT_PMC_PCI_DEVICE_ID 0x9d21 > #define SPT_PMC_BASE_ADDR_OFFSET 0x48 > @@ -589,6 +594,9 @@ extern void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid); > extern void pmc_core_set_device_d3(unsigned int device); > > extern int pmc_core_ssram_init(struct pmc_dev *pmcdev, int func); > +extern const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid); > +extern int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base, > + const struct pmc_reg_map *reg_map, int pmc_index); > > int spt_core_init(struct pmc_dev *pmcdev); > int cnp_core_init(struct pmc_dev *pmcdev); > diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c > index 1bde86c54eb9..0a2bfca5ff41 100644 > --- a/drivers/platform/x86/intel/pmc/core_ssram.c > +++ b/drivers/platform/x86/intel/pmc/core_ssram.c > @@ -24,142 +24,8 @@ > #define SSRAM_IOE_OFFSET 0x68 > #define SSRAM_DEVID_OFFSET 0x70 > > -/* PCH query */ > -#define LPM_HEADER_OFFSET 1 > -#define LPM_REG_COUNT 28 > -#define LPM_MODE_OFFSET 1 > - > DEFINE_FREE(pmc_core_iounmap, void __iomem *, iounmap(_T)); > > -static u32 pmc_core_find_guid(struct pmc_info *list, const struct pmc_reg_map *map) > -{ > - for (; list->map; ++list) > - if (list->map == map) > - return list->guid; > - > - return 0; > -} > - > -static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc) > -{ > - struct telem_endpoint *ep; > - const u8 *lpm_indices; > - int num_maps, mode_offset = 0; > - int ret, mode, i; > - int lpm_size; > - u32 guid; > - > - lpm_indices = pmc->map->lpm_reg_index; > - num_maps = pmc->map->lpm_num_maps; > - lpm_size = LPM_MAX_NUM_MODES * num_maps; > - > - guid = pmc_core_find_guid(pmcdev->regmap_list, pmc->map); > - if (!guid) > - return -ENXIO; > - > - ep = pmt_telem_find_and_register_endpoint(pmcdev->ssram_pcidev, guid, 0); > - if (IS_ERR(ep)) { > - dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %ld", > - PTR_ERR(ep)); > - return -EPROBE_DEFER; > - } > - > - pmc->lpm_req_regs = devm_kzalloc(&pmcdev->pdev->dev, > - lpm_size * sizeof(u32), > - GFP_KERNEL); > - if (!pmc->lpm_req_regs) { > - ret = -ENOMEM; > - goto unregister_ep; > - } > - > - /* > - * PMC Low Power Mode (LPM) table > - * > - * In telemetry space, the LPM table contains a 4 byte header followed > - * by 8 consecutive mode blocks (one for each LPM mode). Each block > - * has a 4 byte header followed by a set of registers that describe the > - * IP state requirements for the given mode. The IP mapping is platform > - * specific but the same for each block, making for easy analysis. > - * Platforms only use a subset of the space to track the requirements > - * for their IPs. Callers provide the requirement registers they use as > - * a list of indices. Each requirement register is associated with an > - * IP map that's maintained by the caller. > - * > - * Header > - * +----+----------------------------+----------------------------+ > - * | 0 | REVISION | ENABLED MODES | > - * +----+--------------+-------------+-------------+--------------+ > - * > - * Low Power Mode 0 Block > - * +----+--------------+-------------+-------------+--------------+ > - * | 1 | SUB ID | SIZE | MAJOR | MINOR | > - * +----+--------------+-------------+-------------+--------------+ > - * | 2 | LPM0 Requirements 0 | > - * +----+---------------------------------------------------------+ > - * | | ... | > - * +----+---------------------------------------------------------+ > - * | 29 | LPM0 Requirements 27 | > - * +----+---------------------------------------------------------+ > - * > - * ... > - * > - * Low Power Mode 7 Block > - * +----+--------------+-------------+-------------+--------------+ > - * | | SUB ID | SIZE | MAJOR | MINOR | > - * +----+--------------+-------------+-------------+--------------+ > - * | 60 | LPM7 Requirements 0 | > - * +----+---------------------------------------------------------+ > - * | | ... | > - * +----+---------------------------------------------------------+ > - * | 87 | LPM7 Requirements 27 | > - * +----+---------------------------------------------------------+ > - * > - */ > - mode_offset = LPM_HEADER_OFFSET + LPM_MODE_OFFSET; > - pmc_for_each_mode(i, mode, pmcdev) { > - u32 *req_offset = pmc->lpm_req_regs + (mode * num_maps); > - int m; > - > - for (m = 0; m < num_maps; m++) { > - u8 sample_id = lpm_indices[m] + mode_offset; > - > - ret = pmt_telem_read32(ep, sample_id, req_offset, 1); > - if (ret) { > - dev_err(&pmcdev->pdev->dev, > - "couldn't read Low Power Mode requirements: %d\n", ret); > - devm_kfree(&pmcdev->pdev->dev, pmc->lpm_req_regs); > - goto unregister_ep; > - } > - ++req_offset; > - } > - mode_offset += LPM_REG_COUNT + LPM_MODE_OFFSET; > - } > - > -unregister_ep: > - pmt_telem_unregister_endpoint(ep); > - > - return ret; > -} > - > -int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev) > -{ > - int ret, i; > - > - if (!pmcdev->ssram_pcidev) > - return -ENODEV; > - > - for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) { > - if (!pmcdev->pmcs[i]) > - continue; > - > - ret = pmc_core_get_lpm_req(pmcdev, pmcdev->pmcs[i]); > - if (ret) > - return ret; > - } > - > - return 0; > -} > - > static void > pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram) > { > @@ -203,50 +69,11 @@ pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram) > intel_vsec_register(pcidev, &info); > } > > -static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid) > -{ > - for (; list->map; ++list) > - if (devid == list->devid) > - return list->map; > - > - return NULL; > -} > - > static inline u64 get_base(void __iomem *addr, u32 offset) > { > return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3); > } > > -static int > -pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base, > - const struct pmc_reg_map *reg_map, int pmc_index) > -{ > - struct pmc *pmc = pmcdev->pmcs[pmc_index]; > - > - if (!pwrm_base) > - return -ENODEV; > - > - /* Memory for primary PMC has been allocated in core.c */ > - if (!pmc) { > - pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL); > - if (!pmc) > - return -ENOMEM; > - } > - > - pmc->map = reg_map; > - pmc->base_addr = pwrm_base; > - pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length); > - > - if (!pmc->regbase) { > - devm_kfree(&pmcdev->pdev->dev, pmc); > - return -ENOMEM; > - } > - > - pmcdev->pmcs[pmc_index] = pmc; > - > - return 0; > -} > - > static int > pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset) > { > -- i.