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@linux.intel.com>
---
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)
{
--
2.43.0
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@linux.intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> ---
> 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.
© 2016 - 2025 Red Hat, Inc.