Skip to contentSkip to conversation

Create Intel PMC SSRAM Telemetry driver

PATCH Superseded Xi Pardee 2 participants 26 messages Aug 28, 2024 – Sep 10, 2024

Subsystems (2)

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Xi Pardee

author maintainer
#0 lore raw

v2 cover Create Intel PMC SSRAM Telemetry driver

This patch series removes the SSRAM support from Intel PMC Core driver and creates a separate PCI driver for SSRAM device. The new Intel PMC SSRAM driver provides the following functionalities:

1. Search and store the PMC information in a structure, including PWRMBASE address and devid for each available PMC. Then Intel PMC Core driver achieves the PMC information using the API provided by the new driver.

2. Search and register Intel Platform Monitoring Techology telemetry regions so they would by available for read through sysfs and Intel PMT API. Intel PMC Core driver can achieve Low Power Mode requirement information from a telemetry region registered by the new driver.

The above functionalities was previously handled by Intel PMC Core driver. Intel PMC Core driver returns -EPROBE_DEFER when trying to read data from a telem region that is not available yet. This setup may result in an infinite loop of .probe() calls as Intel PMC Core driver creates child devices. Creating a separate PCI driver avoids the infinite loop possibility.

Changes in v2:
- Rearrange and restructure patches completely based on feedback from v1
- Here are the patches:

Preparation for the new SSRAM Telemetry driver:
platform/x86:intel/pmc: Move PMC Core related functions platform/x86:intel/pmc: Rename core_ssram to ssram_telemetry platform/x86:intel/pmc: Move PMC devid to core.h

Minor bug fix:
platform/x86:intel/pmc: Convert index variables to be unsigned platform/x86:intel/pmc: Remove unneeded h file inclusion platform/x86:intel/pmc: Remove unneeded io operations platform/x86:intel/pmc: Check return value of ioremap

Create new driver and convert PMC Core to use the API:
platform/x86:intel/pmc: Create Intel PMC SSRAM Telemetry driver

Enable Lunar Lake platform:
platform/x86:intel/pmc: Add Lunar Lake SSRAM devid platform/x86:intel/pmt: Get PMC from SSRAM for Lunar Lake platform/x86:intel/pmc: Get LPM information for Lunar Lake

Xi Pardee (11):
platform/x86:intel/pmc: Move PMC Core related functions platform/x86:intel/pmc: Rename core_ssram to ssram_telemetry platform/x86:intel/pmc: Move PMC devid to core.h platform/x86:intel/pmc: Convert index variables to be unsigned platform/x86:intel/pmc: Remove unneeded h file inclusion platform/x86:intel/pmc: Remove unneeded io operations platform/x86:intel/pmc: Check return value of ioremap platform/x86:intel/pmc: Create Intel PMC SSRAM Telemetry driver platform/x86:intel/pmc: Add Lunar Lake SSRAM devid platform/x86:intel/pmt: Get PMC from SSRAM for Lunar Lake platform/x86:intel/pmc: Get LPM information for Lunar Lake

 drivers/platform/x86/intel/pmc/Kconfig        |  11 +
 drivers/platform/x86/intel/pmc/Makefile       |   8 +-
 drivers/platform/x86/intel/pmc/arl.c          |  24 +-
 drivers/platform/x86/intel/pmc/core.c         | 200 +++++++++++
 drivers/platform/x86/intel/pmc/core.h         |  23 +-
 drivers/platform/x86/intel/pmc/core_ssram.c   | 326 ------------------
 drivers/platform/x86/intel/pmc/lnl.c          |  41 ++-
 drivers/platform/x86/intel/pmc/mtl.c          |  24 +-
 .../platform/x86/intel/pmc/ssram_telemetry.c  | 183 ++++++++++
 .../platform/x86/intel/pmc/ssram_telemetry.h  |  45 +++
 10 files changed, 525 insertions(+), 360 deletions(-)
 delete mode 100644 drivers/platform/x86/intel/pmc/core_ssram.c
 create mode 100644 drivers/platform/x86/intel/pmc/ssram_telemetry.c
 create mode 100644 drivers/platform/x86/intel/pmc/ssram_telemetry.h
Signature · 1 line
2.43.0
author maintainer
#1 lore raw

PATCH v2 1/11 platform/x86:intel/pmc: Move PMC Core related functions

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.

---
 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(-)
drivers/platform/x86/intel/pmc/core.c +168 -0
index 01ae71c6df59..630ce2087552 100644
@@ -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");
drivers/platform/x86/intel/pmc/core.h +8 -0
index ea04de7eb9e8..9a1cc01f31d9 100644
@@ -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);
drivers/platform/x86/intel/pmc/core_ssram.c +0 -173

192 lines not on this page · raw message

Signature · 1 line
2.43.0
maintainer Reviewed-by on v2 1/11
#2 lore raw

Re: [PATCH v2 01/11] platform/x86:intel/pmc: Move PMC Core related functions

Quoted 5 lines · Xi Pardee

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.

Quoted 416 lines
---
 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(-)
drivers/platform/x86/intel/pmc/core.c +168 -0
index 01ae71c6df59..630ce2087552 100644
@@ -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");
drivers/platform/x86/intel/pmc/core.h +8 -0
index ea04de7eb9e8..9a1cc01f31d9 100644
@@ -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);
drivers/platform/x86/intel/pmc/core_ssram.c +0 -173
index 1bde86c54eb9..0a2bfca5ff41 100644
@@ -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)
 {
Signature · 1 line
 i.
author maintainer
#3 lore raw

PATCH v2 2/11 platform/x86:intel/pmc: Rename core_ssram to ssram_telemetry

In reply to Xi Pardee

Rename core_ssram.c to ssram_telemetry.c. This patch is a preparation step to introduce a new SSRAM Telemetry driver for the SSRAM device.

---
 drivers/platform/x86/intel/pmc/Makefile                         | 2 +-
 .../platform/x86/intel/pmc/{core_ssram.c => ssram_telemetry.c}  | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/platform/x86/intel/pmc/{core_ssram.c => ssram_telemetry.c} (100%)
drivers/platform/x86/intel/pmc/Makefile +1 -1
index 389e5419dadf..4dd9fa93f873 100644
@@ -3,7 +3,7 @@
 # Intel x86 Platform-Specific Drivers
 #
 
-intel_pmc_core-y			:= core.o core_ssram.o spt.o cnp.o \
+intel_pmc_core-y			:= core.o ssram_telemetry.o spt.o cnp.o \
 					   icl.o tgl.o adl.o mtl.o arl.o lnl.o
 obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core.o
 intel_pmc_core_pltdrv-y			:= pltdrv.o
drivers/platform/x86/intel/pmc/ssram_telemetry.c renamed from drivers/platform/x86/intel/pmc/core_ssram.c +0 -0
similarity index 100%
rename from drivers/platform/x86/intel/pmc/core_ssram.c
rename to drivers/platform/x86/intel/pmc/ssram_telemetry.c
Signature · 1 line
2.43.0
maintainer Reviewed-by on v2 2/11
#4 lore raw

Re: [PATCH v2 02/11] platform/x86:intel/pmc: Rename core_ssram to ssram_telemetry

Quoted 5 lines · Xi Pardee

Rename core_ssram.c to ssram_telemetry.c. This patch is a preparation step to introduce a new SSRAM Telemetry driver for the SSRAM device.

Signature · 1 line
 i.
Quoted 24 lines
---
 drivers/platform/x86/intel/pmc/Makefile                         | 2 +-
 .../platform/x86/intel/pmc/{core_ssram.c => ssram_telemetry.c}  | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/platform/x86/intel/pmc/{core_ssram.c => ssram_telemetry.c} (100%)
drivers/platform/x86/intel/pmc/Makefile +1 -1
index 389e5419dadf..4dd9fa93f873 100644
@@ -3,7 +3,7 @@
 # Intel x86 Platform-Specific Drivers
 #
 
-intel_pmc_core-y			:= core.o core_ssram.o spt.o cnp.o \
+intel_pmc_core-y			:= core.o ssram_telemetry.o spt.o cnp.o \
 					   icl.o tgl.o adl.o mtl.o arl.o lnl.o
 obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core.o
 intel_pmc_core_pltdrv-y			:= pltdrv.o
drivers/platform/x86/intel/pmc/ssram_telemetry.c renamed from drivers/platform/x86/intel/pmc/core_ssram.c +0 -0
similarity index 100%
rename from drivers/platform/x86/intel/pmc/core_ssram.c
rename to drivers/platform/x86/intel/pmc/ssram_telemetry.c
author maintainer
#5 lore raw

PATCH v2 3/11 platform/x86:intel/pmc: Move PMC devid to core.h

In reply to Xi Pardee

Move PMC devid definition for each PMC of Arrow Lake and Meteor Lake platforms to core.h. This patch is a preparation step to introduce a new SSRAM Telemetry driver which will be using the PMC devid.

---
 drivers/platform/x86/intel/pmc/arl.c  |  9 +++------
 drivers/platform/x86/intel/pmc/core.h | 10 ++++++++++
 drivers/platform/x86/intel/pmc/mtl.c  |  9 +++------
 3 files changed, 16 insertions(+), 12 deletions(-)
drivers/platform/x86/intel/pmc/arl.c +3 -6
index e10527c4e3e0..870da98ceb41 100644
@@ -650,23 +650,20 @@ const struct pmc_reg_map arl_pchs_reg_map = {
 	.etr3_offset = ETR3_OFFSET,
 };
 
-#define PMC_DEVID_SOCS 0xae7f
-#define PMC_DEVID_IOEP 0x7ecf
-#define PMC_DEVID_PCHS 0x7f27
 static struct pmc_info arl_pmc_info_list[] = {
 	{
 		.guid	= IOEP_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_IOEP,
+		.devid	= PMC_DEVID_MTL_IOEP,
 		.map	= &mtl_ioep_reg_map,
 	},
 	{
 		.guid	= SOCS_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_SOCS,
+		.devid	= PMC_DEVID_ARL_SOCS,
 		.map	= &arl_socs_reg_map,
 	},
 	{
 		.guid	= PCHS_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_PCHS,
+		.devid	= PMC_DEVID_ARL_PCHS,
 		.map	= &arl_pchs_reg_map,
 	},
 	{}
drivers/platform/x86/intel/pmc/core.h +10 -0
index 9a1cc01f31d9..6763e59180a4 100644
@@ -290,6 +290,16 @@ enum ppfear_regs {
 #define LNL_PPFEAR_NUM_ENTRIES			12
 #define LNL_S0IX_BLOCKER_OFFSET			0x2004
 
+/* SSRAM PMC Device ID*/
+/* ARL */
+#define PMC_DEVID_ARL_SOCS	0xae7f
+#define PMC_DEVID_ARL_PCHS	0x7f27
+
+/* MTL */
+#define PMC_DEVID_MTL_SOCM	0x7e7f
+#define PMC_DEVID_MTL_IOEP	0x7ecf
+#define PMC_DEVID_MTL_IOEM	0x7ebf
+
 extern const char *pmc_lpm_modes[];
 
 struct pmc_bit_map {
drivers/platform/x86/intel/pmc/mtl.c +3 -6
index c7d15d864039..908b5f8bb6e5 100644
@@ -947,23 +947,20 @@ const struct pmc_reg_map mtl_ioem_reg_map = {
 	.lpm_reg_index = MTL_LPM_REG_INDEX,
 };
 
-#define PMC_DEVID_SOCM	0x7e7f
-#define PMC_DEVID_IOEP	0x7ecf
-#define PMC_DEVID_IOEM	0x7ebf
 static struct pmc_info mtl_pmc_info_list[] = {
 	{
 		.guid	= SOCP_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_SOCM,
+		.devid	= PMC_DEVID_MTL_SOCM,
 		.map	= &mtl_socm_reg_map,
 	},
 	{
 		.guid	= IOEP_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_IOEP,
+		.devid	= PMC_DEVID_MTL_IOEP,
 		.map	= &mtl_ioep_reg_map,
 	},
 	{
 		.guid	= IOEM_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_IOEM,
+		.devid	= PMC_DEVID_MTL_IOEM,
 		.map	= &mtl_ioem_reg_map
 	},
 	{}
Signature · 1 line
2.43.0
maintainer Reviewed-by on v2 3/11
#6 lore raw

Re: [PATCH v2 03/11] platform/x86:intel/pmc: Move PMC devid to core.h

Quoted 48 lines · Xi Pardee

Move PMC devid definition for each PMC of Arrow Lake and Meteor Lake platforms to core.h. This patch is a preparation step to introduce a new SSRAM Telemetry driver which will be using the PMC devid.

---
 drivers/platform/x86/intel/pmc/arl.c  |  9 +++------
 drivers/platform/x86/intel/pmc/core.h | 10 ++++++++++
 drivers/platform/x86/intel/pmc/mtl.c  |  9 +++------
 3 files changed, 16 insertions(+), 12 deletions(-)
drivers/platform/x86/intel/pmc/arl.c +3 -6
index e10527c4e3e0..870da98ceb41 100644
@@ -650,23 +650,20 @@ const struct pmc_reg_map arl_pchs_reg_map = {
 	.etr3_offset = ETR3_OFFSET,
 };
 
-#define PMC_DEVID_SOCS 0xae7f
-#define PMC_DEVID_IOEP 0x7ecf
-#define PMC_DEVID_PCHS 0x7f27
 static struct pmc_info arl_pmc_info_list[] = {
 	{
 		.guid	= IOEP_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_IOEP,
+		.devid	= PMC_DEVID_MTL_IOEP,
 		.map	= &mtl_ioep_reg_map,
 	},
 	{
 		.guid	= SOCS_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_SOCS,
+		.devid	= PMC_DEVID_ARL_SOCS,
 		.map	= &arl_socs_reg_map,
 	},
 	{
 		.guid	= PCHS_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_PCHS,
+		.devid	= PMC_DEVID_ARL_PCHS,
 		.map	= &arl_pchs_reg_map,
 	},
 	{}
drivers/platform/x86/intel/pmc/core.h +0 -0
index 9a1cc01f31d9..6763e59180a4 100644

drivers/platform/x86/intel/pmc/core.h enum ppfear_regs { · line 293

Quoted 4 lines
drivers/platform/x86/intel/pmc/core.h +1 -0
@@ -290,6 +290,16 @@ enum ppfear_regs {
 #define LNL_PPFEAR_NUM_ENTRIES			12
 #define LNL_S0IX_BLOCKER_OFFSET			0x2004
 
+/* SSRAM PMC Device ID*/

Missing space.

Signature · 1 line
 i.
Quoted 44 lines
drivers/platform/x86/intel/pmc/core.h +9 -0
+/* ARL */
+#define PMC_DEVID_ARL_SOCS	0xae7f
+#define PMC_DEVID_ARL_PCHS	0x7f27
+
+/* MTL */
+#define PMC_DEVID_MTL_SOCM	0x7e7f
+#define PMC_DEVID_MTL_IOEP	0x7ecf
+#define PMC_DEVID_MTL_IOEM	0x7ebf
+
 extern const char *pmc_lpm_modes[];
 
 struct pmc_bit_map {
drivers/platform/x86/intel/pmc/mtl.c +3 -6
index c7d15d864039..908b5f8bb6e5 100644
@@ -947,23 +947,20 @@ const struct pmc_reg_map mtl_ioem_reg_map = {
 	.lpm_reg_index = MTL_LPM_REG_INDEX,
 };
 
-#define PMC_DEVID_SOCM	0x7e7f
-#define PMC_DEVID_IOEP	0x7ecf
-#define PMC_DEVID_IOEM	0x7ebf
 static struct pmc_info mtl_pmc_info_list[] = {
 	{
 		.guid	= SOCP_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_SOCM,
+		.devid	= PMC_DEVID_MTL_SOCM,
 		.map	= &mtl_socm_reg_map,
 	},
 	{
 		.guid	= IOEP_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_IOEP,
+		.devid	= PMC_DEVID_MTL_IOEP,
 		.map	= &mtl_ioep_reg_map,
 	},
 	{
 		.guid	= IOEM_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_IOEM,
+		.devid	= PMC_DEVID_MTL_IOEM,
 		.map	= &mtl_ioem_reg_map
 	},
 	{}
author maintainer
#7 lore raw

Re: [PATCH v2 03/11] platform/x86:intel/pmc: Move PMC devid to core.h

Quoted 53 lines · Ilpo Järvinen
Quoted 51 lines · Xi Pardee

Move PMC devid definition for each PMC of Arrow Lake and Meteor Lake platforms to core.h. This patch is a preparation step to introduce a new SSRAM Telemetry driver which will be using the PMC devid.

---
  drivers/platform/x86/intel/pmc/arl.c  |  9 +++------
  drivers/platform/x86/intel/pmc/core.h | 10 ++++++++++
  drivers/platform/x86/intel/pmc/mtl.c  |  9 +++------
  3 files changed, 16 insertions(+), 12 deletions(-)
drivers/platform/x86/intel/pmc/arl.c +3 -6
index e10527c4e3e0..870da98ceb41 100644
@@ -650,23 +650,20 @@ const struct pmc_reg_map arl_pchs_reg_map = {
  	.etr3_offset = ETR3_OFFSET,
  };
 
-#define PMC_DEVID_SOCS 0xae7f
-#define PMC_DEVID_IOEP 0x7ecf
-#define PMC_DEVID_PCHS 0x7f27
  static struct pmc_info arl_pmc_info_list[] = {
  	{
  		.guid	= IOEP_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_IOEP,
+		.devid	= PMC_DEVID_MTL_IOEP,
  		.map	= &mtl_ioep_reg_map,
  	},
  	{
  		.guid	= SOCS_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_SOCS,
+		.devid	= PMC_DEVID_ARL_SOCS,
  		.map	= &arl_socs_reg_map,
  	},
  	{
  		.guid	= PCHS_LPM_REQ_GUID,
-		.devid	= PMC_DEVID_PCHS,
+		.devid	= PMC_DEVID_ARL_PCHS,
  		.map	= &arl_pchs_reg_map,
  	},
  	{}
drivers/platform/x86/intel/pmc/core.h +0 -0
index 9a1cc01f31d9..6763e59180a4 100644
@@ -290,6 +290,16 @@ enum ppfear_regs {
  #define LNL_PPFEAR_NUM_ENTRIES			12
  #define LNL_S0IX_BLOCKER_OFFSET			0x2004
 
Quoted 4 lines

drivers/platform/x86/intel/pmc/core.h enum ppfear_regs { · line 293

Quoted 1 line
drivers/platform/x86/intel/pmc/core.h +1 -0
+/* SSRAM PMC Device ID*/

Missing space.

Will add a space in next version.

Thanks!

Xi

Quoted 1 line
author maintainer
#8 lore raw

PATCH v2 4/11 platform/x86:intel/pmc: Convert index variables to be unsigned

In reply to Xi Pardee

Convert the index variables type to be unsigned to avoid confusion and error.

---
 drivers/platform/x86/intel/pmc/core.c            | 5 +++--
 drivers/platform/x86/intel/pmc/core.h            | 2 +-
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)
drivers/platform/x86/intel/pmc/core.c +3 -2
index 630ce2087552..8984041f35f4 100644
@@ -1716,7 +1716,8 @@ static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
 
 int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev)
 {
-	int ret, i;
+	unsigned int i;
+	int ret;
 
 	if (!pmcdev->ssram_pcidev)
 		return -ENODEV;
@@ -1743,7 +1744,7 @@ const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
 }
 
 int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
-		     const struct pmc_reg_map *reg_map, int pmc_index)
+		     const struct pmc_reg_map *reg_map, unsigned int pmc_index)
 {
 	struct pmc *pmc = pmcdev->pmcs[pmc_index];
 
drivers/platform/x86/intel/pmc/core.h +1 -1
index 6763e59180a4..5af1d41a83f7 100644
@@ -606,7 +606,7 @@ 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);
+			    const struct pmc_reg_map *reg_map, unsigned int pmc_index);
 
 int spt_core_init(struct pmc_dev *pmcdev);
 int cnp_core_init(struct pmc_dev *pmcdev);
drivers/platform/x86/intel/pmc/ssram_telemetry.c +1 -1
index 0a2bfca5ff41..4b21d9cf310a 100644
@@ -75,7 +75,7 @@ static inline u64 get_base(void __iomem *addr, u32 offset)
 }
 
 static int
-pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset)
+pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
 {
 	struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
 	void __iomem __free(pmc_core_iounmap) *tmp_ssram = NULL;
Signature · 1 line
2.43.0
maintainer Reviewed-by on v2 4/11
#9 lore raw

Re: [PATCH v2 04/11] platform/x86:intel/pmc: Convert index variables to be unsigned

Quoted 4 lines · Xi Pardee

Convert the index variables type to be unsigned to avoid confusion and error.

Signature · 1 line
 i.
Quoted 56 lines
---
 drivers/platform/x86/intel/pmc/core.c            | 5 +++--
 drivers/platform/x86/intel/pmc/core.h            | 2 +-
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)
drivers/platform/x86/intel/pmc/core.c +3 -2
index 630ce2087552..8984041f35f4 100644
@@ -1716,7 +1716,8 @@ static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
 
 int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev)
 {
-	int ret, i;
+	unsigned int i;
+	int ret;
 
 	if (!pmcdev->ssram_pcidev)
 		return -ENODEV;
@@ -1743,7 +1744,7 @@ const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
 }
 
 int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
-		     const struct pmc_reg_map *reg_map, int pmc_index)
+		     const struct pmc_reg_map *reg_map, unsigned int pmc_index)
 {
 	struct pmc *pmc = pmcdev->pmcs[pmc_index];
 
drivers/platform/x86/intel/pmc/core.h +1 -1
index 6763e59180a4..5af1d41a83f7 100644
@@ -606,7 +606,7 @@ 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);
+			    const struct pmc_reg_map *reg_map, unsigned int pmc_index);
 
 int spt_core_init(struct pmc_dev *pmcdev);
 int cnp_core_init(struct pmc_dev *pmcdev);
drivers/platform/x86/intel/pmc/ssram_telemetry.c +1 -1
index 0a2bfca5ff41..4b21d9cf310a 100644
@@ -75,7 +75,7 @@ static inline u64 get_base(void __iomem *addr, u32 offset)
 }
 
 static int
-pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset)
+pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
 {
 	struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
 	void __iomem __free(pmc_core_iounmap) *tmp_ssram = NULL;
author maintainer
#10 lore raw

PATCH v2 5/11 platform/x86:intel/pmc: Remove unneeded h file inclusion

In reply to Xi Pardee

telemetry.h header file is not needed in arl.c or mtl.c. Remove them to avoid confusion.

---
 drivers/platform/x86/intel/pmc/arl.c | 1 -
 drivers/platform/x86/intel/pmc/mtl.c | 1 -
 2 files changed, 2 deletions(-)
drivers/platform/x86/intel/pmc/arl.c +0 -1
index 870da98ceb41..0460715c58f4 100644
@@ -10,7 +10,6 @@
 
 #include <linux/pci.h>
 #include "core.h"
-#include "../pmt/telemetry.h"
 
 /* PMC SSRAM PMT Telemetry GUID */
 #define IOEP_LPM_REQ_GUID	0x5077612
drivers/platform/x86/intel/pmc/mtl.c +0 -1
index 908b5f8bb6e5..e7f5b650902d 100644
@@ -10,7 +10,6 @@
 
 #include <linux/pci.h>
 #include "core.h"
-#include "../pmt/telemetry.h"
 
 /* PMC SSRAM PMT Telemetry GUIDS */
 #define SOCP_LPM_REQ_GUID	0x2625030
Signature · 1 line
2.43.0
maintainer Reviewed-by on v2 5/11
#11 lore raw

Re: [PATCH v2 05/11] platform/x86:intel/pmc: Remove unneeded h file inclusion

On Wed, 28 Aug 2024, Xi Pardee wrote:

In the subject:

h file -> header

Quoted 2 lines

telemetry.h header file is not needed in arl.c or mtl.c. Remove them to avoid confusion.

I'd also note this is cross directory/driver include, so perhaps something along these lines:

telemetry.h from PMT is not needed in arl.c or mtl.c so remove the cross-driver include.

Signature · 1 line
 i.
Quoted 31 lines
---
 drivers/platform/x86/intel/pmc/arl.c | 1 -
 drivers/platform/x86/intel/pmc/mtl.c | 1 -
 2 files changed, 2 deletions(-)
drivers/platform/x86/intel/pmc/arl.c +0 -1
index 870da98ceb41..0460715c58f4 100644
@@ -10,7 +10,6 @@
 
 #include <linux/pci.h>
 #include "core.h"
-#include "../pmt/telemetry.h"
 
 /* PMC SSRAM PMT Telemetry GUID */
 #define IOEP_LPM_REQ_GUID	0x5077612
drivers/platform/x86/intel/pmc/mtl.c +0 -1
index 908b5f8bb6e5..e7f5b650902d 100644
@@ -10,7 +10,6 @@
 
 #include <linux/pci.h>
 #include "core.h"
-#include "../pmt/telemetry.h"
 
 /* PMC SSRAM PMT Telemetry GUIDS */
 #define SOCP_LPM_REQ_GUID	0x2625030
author maintainer
#12 lore raw

Re: [PATCH v2 05/11] platform/x86:intel/pmc: Remove unneeded h file inclusion

Quoted 8 lines · Ilpo Järvinen

On Wed, 28 Aug 2024, Xi Pardee wrote:

In the subject:

h file -> header

Quoted 2 lines

telemetry.h header file is not needed in arl.c or mtl.c. Remove them to avoid confusion.

Quoted 7 lines

I'd also note this is cross directory/driver include, so perhaps something along these lines:

telemetry.h from PMT is not needed in arl.c or mtl.c so remove the cross-driver include.

Thanks! I will modify the commit message in the next version.

Xi

author maintainer
#13 lore raw

PATCH v2 6/11 platform/x86:intel/pmc: Remove unneeded io operations

In reply to Xi Pardee

Remove ioremap and iounmap operations that are not needed. ioremap and iounmap operations are handled by the caller of the pmc_add_pmt function.

---
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 6 ------
 1 file changed, 6 deletions(-)
drivers/platform/x86/intel/pmc/ssram_telemetry.c +0 -6
index 4b21d9cf310a..73c727042ca6 100644
@@ -37,13 +37,7 @@ pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram)
 	u32 dvsec_offset;
 	u32 table, hdr;
 
-	ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
-	if (!ssram)
-		return;
-
 	dvsec_offset = readl(ssram + SSRAM_DVSEC_OFFSET);
-	iounmap(ssram);
-
 	dvsec = ioremap(ssram_base + dvsec_offset, SSRAM_DVSEC_SIZE);
 	if (!dvsec)
 		return;
Signature · 1 line
2.43.0
author maintainer
#14 lore raw

PATCH v2 7/11 platform/x86:intel/pmc: Check return value of ioremap

In reply to Xi Pardee

Check the return value of ioremap operation and return ENOMEM when the operation fails for better error handling.

---
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/platform/x86/intel/pmc/ssram_telemetry.c +3 -0
index 73c727042ca6..f625d39d1aa3 100644
@@ -84,6 +84,9 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
 	ssram_base = ssram_pcidev->resource[0].start;
 	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
 
+	if (!tmp_ssram)
+		return -ENOMEM;
+
 	if (pmc_idx != PMC_IDX_MAIN) {
 		/*
 		 * The secondary PMC BARS (which are behind hidden PCI devices)
Signature · 1 line
2.43.0
maintainer
#15 lore raw

Re: [PATCH v2 07/11] platform/x86:intel/pmc: Check return value of ioremap

Quoted 13 lines · Xi Pardee

Check the return value of ioremap operation and return ENOMEM when the operation fails for better error handling.

---
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/platform/x86/intel/pmc/ssram_telemetry.c +0 -0
index 73c727042ca6..f625d39d1aa3 100644

drivers/platform/x86/intel/pmc/ssram_telemetry.c pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset) · line 92

Quoted 9 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +3 -0
@@ -84,6 +84,9 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
 	ssram_base = ssram_pcidev->resource[0].start;
 	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
 
+	if (!tmp_ssram)
+		return -ENOMEM;
+
 	if (pmc_idx != PMC_IDX_MAIN) {
 		/*
 		 * The secondary PMC BARS (which are behind hidden PCI devices)

Is this a fix to the current code? And should have Fixes tag and go first because of that?

Signature · 1 line
 i.
author maintainer
#16 lore raw

Re: [PATCH v2 07/11] platform/x86:intel/pmc: Check return value of ioremap

Quoted 18 lines · Ilpo Järvinen
Quoted 16 lines · Xi Pardee

Check the return value of ioremap operation and return ENOMEM when the operation fails for better error handling.

---
  drivers/platform/x86/intel/pmc/ssram_telemetry.c | 3 +++
  1 file changed, 3 insertions(+)
drivers/platform/x86/intel/pmc/ssram_telemetry.c +0 -0
index 73c727042ca6..f625d39d1aa3 100644
@@ -84,6 +84,9 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
  	ssram_base = ssram_pcidev->resource[0].start;
  	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
 
Quoted 8 lines

drivers/platform/x86/intel/pmc/ssram_telemetry.c pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset) · line 92

Quoted 6 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +3 -0
+	if (!tmp_ssram)
+		return -ENOMEM;
+
  	if (pmc_idx != PMC_IDX_MAIN) {
  		/*
  		 * The secondary PMC BARS (which are behind hidden PCI devices)

Is this a fix to the current code? And should have Fixes tag and go first because of that?

This is an improvement of the current code. We should check the value of ioremap before using it to avoid failure in the later process. I can add a fixes tag to it. Should this patch be its own patch series and not include in this one? Or should it be moved to be the first patch of this series?

Thanks!
Xi

Quoted 1 line
author maintainer
#17 lore raw

PATCH v2 8/11 platform/x86:intel/pmc: Create Intel PMC SSRAM Telemetry driver

In reply to Xi Pardee

Convert ssram device related functionalities to a new driver named Intel PMC SSRAM Telemetry driver. Modify PMC Core driver to use API exported by the driver to discover and achieve devid and PWRMBASE address information for each available PMC. PMC Core driver needs to get PCI device when reading from telemetry regions.

The new SSRAM driver binds to the SSRAM device and provides the following functionalities:
1. Look for and register telemetry regions available in SSRAM device.
2. Provide devid and PWRMBASE address information for the corresponding PMCs.

---
 drivers/platform/x86/intel/pmc/Kconfig        |  11 ++
 drivers/platform/x86/intel/pmc/Makefile       |   8 +-
 drivers/platform/x86/intel/pmc/arl.c          |  14 ++-
 drivers/platform/x86/intel/pmc/core.c         |  59 ++++++---
 drivers/platform/x86/intel/pmc/core.h         |   6 +-
 drivers/platform/x86/intel/pmc/mtl.c          |  14 ++-
 .../platform/x86/intel/pmc/ssram_telemetry.c  | 118 +++++++++++-------
 .../platform/x86/intel/pmc/ssram_telemetry.h  |  45 +++++++
 8 files changed, 200 insertions(+), 75 deletions(-)
 create mode 100644 drivers/platform/x86/intel/pmc/ssram_telemetry.h
drivers/platform/x86/intel/pmc/Kconfig +11 -0
index d2f651fbec2c..c2ccd48fe266 100644
@@ -8,6 +8,7 @@ config INTEL_PMC_CORE
 	depends on PCI
 	depends on ACPI
 	depends on INTEL_PMT_TELEMETRY
+	depends on INTEL_PMC_SSRAM_TELEMETRY || !INTEL_PMC_SSRAM_TELEMETRY
 	help
 	  The Intel Platform Controller Hub for Intel Core SoCs provides access
 	  to Power Management Controller registers via various interfaces. This
@@ -24,3 +25,13 @@ config INTEL_PMC_CORE
 		- SLPS0 Debug registers (Cannonlake/Icelake PCH)
 		- Low Power Mode registers (Tigerlake and beyond)
 		- PMC quirks as needed to enable SLPS0/S0ix
+
+config INTEL_PMC_SSRAM_TELEMETRY
+	tristate "Intel PMC SSRAM Telemetry driver"
+	depends on INTEL_VSEC
+	help
+	  The PMC SSRAM device contains counters structured in Intel Platform
+	  Monitoring Techology (PMT) telemetry regions. This driver looks for
+	  and register these telemetry regions so they would be available for
+	  read through sysfs and Intel PMT API. The driver also provides API to
+	  expose information of PMCs available in the platform.
\ No newline at end of file
drivers/platform/x86/intel/pmc/Makefile +6 -2
index 4dd9fa93f873..e935602af2a3 100644
@@ -3,8 +3,12 @@
 # Intel x86 Platform-Specific Drivers
 #
 
-intel_pmc_core-y			:= core.o ssram_telemetry.o spt.o cnp.o \
-					   icl.o tgl.o adl.o mtl.o arl.o lnl.o
+intel_pmc_core-y			:= core.o spt.o cnp.o icl.o \
+					   tgl.o adl.o mtl.o arl.o lnl.o
 obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core.o
 intel_pmc_core_pltdrv-y			:= pltdrv.o
 obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core_pltdrv.o
+
+# Intel PMC SSRAM driver
+intel_pmc_ssram_telemetry-y		+= ssram_telemetry.o
+obj-$(CONFIG_INTEL_PMC_SSRAM_TELEMETRY)	+= intel_pmc_ssram_telemetry.o
\ No newline at end of file
drivers/platform/x86/intel/pmc/arl.c +8 -6
index 0460715c58f4..25268b1fdf97 100644
@@ -700,11 +700,13 @@ int arl_core_init(struct pmc_dev *pmcdev)
 	pmcdev->resume = arl_resume;
 	pmcdev->regmap_list = arl_pmc_info_list;
 
-	/*
-	 * If ssram init fails use legacy method to at least get the
-	 * primary PMC
-	 */
-	ret = pmc_core_ssram_init(pmcdev, func);
+	ret = pmc_core_ssram_get_reg_base(pmcdev);
+
+	/* Try again later after Intel PMC SSRAM Telemetry driver finishes probe */
+	if (ret == -EAGAIN)
+		return -EPROBE_DEFER;
+
+	/* If regbase not assigned, set map and discover using legacy method */
 	if (ret) {
 		ssram_init = false;
 		pmc->map = &arl_socs_reg_map;
@@ -718,7 +720,7 @@ int arl_core_init(struct pmc_dev *pmcdev)
 	pmc_core_punit_pmt_init(pmcdev, ARL_PMT_DMU_GUID);
 
 	if (ssram_init)	{
-		ret = pmc_core_ssram_get_lpm_reqs(pmcdev);
+		ret = pmc_core_ssram_get_lpm_reqs(pmcdev, func);
 		if (ret)
 			return ret;
 	}
drivers/platform/x86/intel/pmc/core.c +45 -14

124 lines not on this page · raw message

drivers/platform/x86/intel/pmc/core.h +2 -4
index 5af1d41a83f7..2d62a71ec100 100644
@@ -594,7 +594,7 @@ extern const struct pmc_bit_map *arl_pchs_lpm_maps[];
 extern const struct pmc_reg_map arl_pchs_reg_map;
 
 extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
-extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev);
+extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev, int func);
 int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore);
 
 int pmc_core_resume_common(struct pmc_dev *pmcdev);
@@ -603,10 +603,8 @@ extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
 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, unsigned int pmc_index);
+extern int pmc_core_ssram_get_reg_base(struct pmc_dev *pmcdev);
 
 int spt_core_init(struct pmc_dev *pmcdev);
 int cnp_core_init(struct pmc_dev *pmcdev);
drivers/platform/x86/intel/pmc/mtl.c +8 -6
index e7f5b650902d..6ac52625a029 100644
@@ -1000,11 +1000,13 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 	pmcdev->resume = mtl_resume;
 	pmcdev->regmap_list = mtl_pmc_info_list;
 
-	/*
-	 * If ssram init fails use legacy method to at least get the
-	 * primary PMC
-	 */
-	ret = pmc_core_ssram_init(pmcdev, func);
+	ret = pmc_core_ssram_get_reg_base(pmcdev);
+
+	/* Try again later after Intel PMC SSRAM Telemetry driver finishes probe */
+	if (ret == -EAGAIN)
+		return -EPROBE_DEFER;
+
+	/* If regbase not assigned, set map and discover using legacy method */
 	if (ret) {
 		ssram_init = false;
 		dev_warn(&pmcdev->pdev->dev,
@@ -1019,7 +1021,7 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 	pmc_core_punit_pmt_init(pmcdev, MTL_PMT_DMU_GUID);
 
 	if (ssram_init)
-		return pmc_core_ssram_get_lpm_reqs(pmcdev);
+		return pmc_core_ssram_get_lpm_reqs(pmcdev, func);
 
 	return 0;
 }
drivers/platform/x86/intel/pmc/ssram_telemetry.c +75 -43

179 lines not on this page · raw message

drivers/platform/x86/intel/pmc/ssram_telemetry.h new file +45 -0

45 lines not on this page · raw message

Signature · 1 line
2.43.0
maintainer
#18 lore raw

Re: [PATCH v2 08/11] platform/x86:intel/pmc: Create Intel PMC SSRAM Telemetry driver

Quoted 62 lines · Xi Pardee

Convert ssram device related functionalities to a new driver named Intel PMC SSRAM Telemetry driver. Modify PMC Core driver to use API exported by the driver to discover and achieve devid and PWRMBASE address information for each available PMC. PMC Core driver needs to get PCI device when reading from telemetry regions.

The new SSRAM driver binds to the SSRAM device and provides the following functionalities:
1. Look for and register telemetry regions available in SSRAM device.
2. Provide devid and PWRMBASE address information for the corresponding PMCs.

---
 drivers/platform/x86/intel/pmc/Kconfig        |  11 ++
 drivers/platform/x86/intel/pmc/Makefile       |   8 +-
 drivers/platform/x86/intel/pmc/arl.c          |  14 ++-
 drivers/platform/x86/intel/pmc/core.c         |  59 ++++++---
 drivers/platform/x86/intel/pmc/core.h         |   6 +-
 drivers/platform/x86/intel/pmc/mtl.c          |  14 ++-
 .../platform/x86/intel/pmc/ssram_telemetry.c  | 118 +++++++++++-------
 .../platform/x86/intel/pmc/ssram_telemetry.h  |  45 +++++++
 8 files changed, 200 insertions(+), 75 deletions(-)
 create mode 100644 drivers/platform/x86/intel/pmc/ssram_telemetry.h
drivers/platform/x86/intel/pmc/Kconfig +11 -0
index d2f651fbec2c..c2ccd48fe266 100644
@@ -8,6 +8,7 @@ config INTEL_PMC_CORE
 	depends on PCI
 	depends on ACPI
 	depends on INTEL_PMT_TELEMETRY
+	depends on INTEL_PMC_SSRAM_TELEMETRY || !INTEL_PMC_SSRAM_TELEMETRY
 	help
 	  The Intel Platform Controller Hub for Intel Core SoCs provides access
 	  to Power Management Controller registers via various interfaces. This
@@ -24,3 +25,13 @@ config INTEL_PMC_CORE
 		- SLPS0 Debug registers (Cannonlake/Icelake PCH)
 		- Low Power Mode registers (Tigerlake and beyond)
 		- PMC quirks as needed to enable SLPS0/S0ix
+
+config INTEL_PMC_SSRAM_TELEMETRY
+	tristate "Intel PMC SSRAM Telemetry driver"
+	depends on INTEL_VSEC
+	help
+	  The PMC SSRAM device contains counters structured in Intel Platform
+	  Monitoring Techology (PMT) telemetry regions. This driver looks for
+	  and register these telemetry regions so they would be available for
+	  read through sysfs and Intel PMT API. The driver also provides API to
+	  expose information of PMCs available in the platform.
\ No newline at end of file
drivers/platform/x86/intel/pmc/Makefile +0 -2
index 4dd9fa93f873..e935602af2a3 100644
@@ -3,8 +3,12 @@
 # Intel x86 Platform-Specific Drivers
 #
 
-intel_pmc_core-y			:= core.o ssram_telemetry.o spt.o cnp.o \
-					   icl.o tgl.o adl.o mtl.o arl.o lnl.o

drivers/platform/x86/intel/pmc/Makefile line 14

Quoted 10 lines
drivers/platform/x86/intel/pmc/Makefile +6 -0
+intel_pmc_core-y			:= core.o spt.o cnp.o icl.o \
+					   tgl.o adl.o mtl.o arl.o lnl.o
 obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core.o
 intel_pmc_core_pltdrv-y			:= pltdrv.o
 obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core_pltdrv.o
+
+# Intel PMC SSRAM driver
+intel_pmc_ssram_telemetry-y		+= ssram_telemetry.o
+obj-$(CONFIG_INTEL_PMC_SSRAM_TELEMETRY)	+= intel_pmc_ssram_telemetry.o
\ No newline at end of file

Two files above are missing the last newline.

Quoted 319 lines
drivers/platform/x86/intel/pmc/arl.c +8 -6
index 0460715c58f4..25268b1fdf97 100644
@@ -700,11 +700,13 @@ int arl_core_init(struct pmc_dev *pmcdev)
 	pmcdev->resume = arl_resume;
 	pmcdev->regmap_list = arl_pmc_info_list;
 
-	/*
-	 * If ssram init fails use legacy method to at least get the
-	 * primary PMC
-	 */
-	ret = pmc_core_ssram_init(pmcdev, func);
+	ret = pmc_core_ssram_get_reg_base(pmcdev);
+
+	/* Try again later after Intel PMC SSRAM Telemetry driver finishes probe */
+	if (ret == -EAGAIN)
+		return -EPROBE_DEFER;
+
+	/* If regbase not assigned, set map and discover using legacy method */
 	if (ret) {
 		ssram_init = false;
 		pmc->map = &arl_socs_reg_map;
@@ -718,7 +720,7 @@ int arl_core_init(struct pmc_dev *pmcdev)
 	pmc_core_punit_pmt_init(pmcdev, ARL_PMT_DMU_GUID);
 
 	if (ssram_init)	{
-		ret = pmc_core_ssram_get_lpm_reqs(pmcdev);
+		ret = pmc_core_ssram_get_lpm_reqs(pmcdev, func);
 		if (ret)
 			return ret;
 	}
drivers/platform/x86/intel/pmc/core.c +45 -14
index 8984041f35f4..19256c5570ab 100644
@@ -28,6 +28,7 @@
 #include <asm/tsc.h>
 
 #include "core.h"
+#include "ssram_telemetry.h"
 #include "../pmt/telemetry.h"
 
 /* Maximum number of modes supported by platfoms that has low power mode capability */
@@ -1613,11 +1614,12 @@ static u32 pmc_core_find_guid(struct pmc_info *list, const struct pmc_reg_map *m
 	return 0;
 }
 
-static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
+static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, int func)
 {
 	struct telem_endpoint *ep;
 	const u8 *lpm_indices;
 	int num_maps, mode_offset = 0;
+	struct pci_dev *pcidev;
 	int ret, mode, i;
 	int lpm_size;
 	u32 guid;
@@ -1630,11 +1632,16 @@ static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
 	if (!guid)
 		return -ENXIO;
 
-	ep = pmt_telem_find_and_register_endpoint(pmcdev->ssram_pcidev, guid, 0);
+	pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, func));
+	if (!pcidev)
+		return -ENODEV;
+
+	ep = pmt_telem_find_and_register_endpoint(pcidev, guid, 0);
 	if (IS_ERR(ep)) {
 		dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %ld",
 			PTR_ERR(ep));
-		return -EPROBE_DEFER;
+		ret = -EPROBE_DEFER;
+		goto release_dev;
 	}
 
 	pmc->lpm_req_regs = devm_kzalloc(&pmcdev->pdev->dev,
@@ -1710,23 +1717,22 @@ static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
 
 unregister_ep:
 	pmt_telem_unregister_endpoint(ep);
+release_dev:
+	pci_dev_put(pcidev);
 
 	return ret;
 }
 
-int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev)
+int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev, int func)
 {
 	unsigned int i;
 	int ret;
 
-	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]);
+		ret = pmc_core_get_lpm_req(pmcdev, pmcdev->pmcs[i], func);
 		if (ret)
 			return ret;
 	}
@@ -1743,14 +1749,22 @@ const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
 	return NULL;
 }
 
-int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
-		     const struct pmc_reg_map *reg_map, unsigned int pmc_index)
+static int pmc_core_pmc_add(struct pmc_dev *pmcdev, unsigned int pmc_index)
 {
-	struct pmc *pmc = pmcdev->pmcs[pmc_index];
+	struct pmc_ssram_telemetry pmc_ssram_telemetry;
+	const struct pmc_reg_map *map;
+	struct pmc *pmc;
+	int ret;
+
+	ret = pmc_ssram_telemetry_get_pmc_info(pmc_index, &pmc_ssram_telemetry);
+	if (ret)
+		return ret;
 
-	if (!pwrm_base)
+	map = pmc_core_find_regmap(pmcdev->regmap_list, pmc_ssram_telemetry.devid);
+	if (!map)
 		return -ENODEV;
 
+	pmc = pmcdev->pmcs[pmc_index];
 	/* Memory for primary PMC has been allocated in core.c */
 	if (!pmc) {
 		pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL);
@@ -1758,8 +1772,8 @@ int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
 			return -ENOMEM;
 	}
 
-	pmc->map = reg_map;
-	pmc->base_addr = pwrm_base;
+	pmc->map = map;
+	pmc->base_addr = pmc_ssram_telemetry.base_addr;
 	pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length);
 
 	if (!pmc->regbase) {
@@ -1772,6 +1786,23 @@ int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
 	return 0;
 }
 
+int pmc_core_ssram_get_reg_base(struct pmc_dev *pmcdev)
+{
+	int ret;
+
+	if (!pmcdev->regmap_list)
+		return -ENOENT;
+
+	ret = pmc_core_pmc_add(pmcdev, PMC_IDX_MAIN);
+	if (ret)
+		return ret;
+
+	pmc_core_pmc_add(pmcdev, PMC_IDX_IOE);
+	pmc_core_pmc_add(pmcdev, PMC_IDX_PCH);
+
+	return 0;
+}
+
 static const struct acpi_device_id pmc_core_acpi_ids[] = {
 	{"INT33A1", 0}, /* _HID for Intel Power Engine, _CID PNP0D80*/
 	{ }
drivers/platform/x86/intel/pmc/core.h +2 -4
index 5af1d41a83f7..2d62a71ec100 100644
@@ -594,7 +594,7 @@ extern const struct pmc_bit_map *arl_pchs_lpm_maps[];
 extern const struct pmc_reg_map arl_pchs_reg_map;
 
 extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
-extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev);
+extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev, int func);
 int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore);
 
 int pmc_core_resume_common(struct pmc_dev *pmcdev);
@@ -603,10 +603,8 @@ extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
 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, unsigned int pmc_index);
+extern int pmc_core_ssram_get_reg_base(struct pmc_dev *pmcdev);
 
 int spt_core_init(struct pmc_dev *pmcdev);
 int cnp_core_init(struct pmc_dev *pmcdev);
drivers/platform/x86/intel/pmc/mtl.c +8 -6
index e7f5b650902d..6ac52625a029 100644
@@ -1000,11 +1000,13 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 	pmcdev->resume = mtl_resume;
 	pmcdev->regmap_list = mtl_pmc_info_list;
 
-	/*
-	 * If ssram init fails use legacy method to at least get the
-	 * primary PMC
-	 */
-	ret = pmc_core_ssram_init(pmcdev, func);
+	ret = pmc_core_ssram_get_reg_base(pmcdev);
+
+	/* Try again later after Intel PMC SSRAM Telemetry driver finishes probe */
+	if (ret == -EAGAIN)
+		return -EPROBE_DEFER;
+
+	/* If regbase not assigned, set map and discover using legacy method */
 	if (ret) {
 		ssram_init = false;
 		dev_warn(&pmcdev->pdev->dev,
@@ -1019,7 +1021,7 @@ int mtl_core_init(struct pmc_dev *pmcdev)
 	pmc_core_punit_pmt_init(pmcdev, MTL_PMT_DMU_GUID);
 
 	if (ssram_init)
-		return pmc_core_ssram_get_lpm_reqs(pmcdev);
+		return pmc_core_ssram_get_lpm_reqs(pmcdev, func);
 
 	return 0;
 }
drivers/platform/x86/intel/pmc/ssram_telemetry.c +21 -20
index f625d39d1aa3..1c6cc95bfefa 100644
@@ -1,20 +1,19 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * This file contains functions to handle discovery of PMC metrics located
- * in the PMC SSRAM PCI device.
+ * Intel PMC SSRAM TELEMETRY PCI Driver
  *
  * Copyright (c) 2023, Intel Corporation.
  * All Rights Reserved.
  *
  */
 
-#include <linux/cleanup.h>
 #include <linux/pci.h>
+#include <linux/types.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 
 #include "core.h"
+#include "ssram_telemetry.h"
 #include "../vsec.h"
-#include "../pmt/telemetry.h"
 
 #define SSRAM_HDR_SIZE		0x100
 #define SSRAM_PWRM_OFFSET	0x14
@@ -24,12 +23,14 @@
 #define SSRAM_IOE_OFFSET	0x68
 #define SSRAM_DEVID_OFFSET	0x70
 
-DEFINE_FREE(pmc_core_iounmap, void __iomem *, iounmap(_T));
+static struct pmc_ssram_telemetry *pmc_ssram_telems;
+static bool device_probed;
+
+DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, iounmap(_T));
 
 static void
-pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram)
+pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem *ssram)
 {
-	struct pci_dev *pcidev = pmcdev->ssram_pcidev;
 	struct intel_vsec_platform_info info = {};
 	struct intel_vsec_header *headers[2] = {};
 	struct intel_vsec_header header;
@@ -58,7 +59,7 @@ pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram)
 	info.caps = VSEC_CAP_TELEMETRY;
 	info.headers = headers;
 	info.base_addr = ssram_base;
-	info.parent = &pmcdev->pdev->dev;
+	info.parent = &pcidev->dev;
 
 	intel_vsec_register(pcidev, &info);
 }
@@ -69,19 +70,14 @@ static inline u64 get_base(void __iomem *addr, u32 offset)
 }
 
 static int
-pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
+pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
 {
-	struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
-	void __iomem __free(pmc_core_iounmap) *tmp_ssram = NULL;
-	void __iomem __free(pmc_core_iounmap) *ssram = NULL;
-	const struct pmc_reg_map *map;
+	void __iomem __free(pmc_ssram_telemetry_iounmap) * tmp_ssram = NULL;
+	void __iomem __free(pmc_ssram_telemetry_iounmap) * ssram = NULL;
 	u64 ssram_base, pwrm_base;
 	u16 devid;
 
-	if (!pmcdev->regmap_list)
-		return -ENOENT;
-
-	ssram_base = ssram_pcidev->resource[0].start;
+	ssram_base = pcidev->resource[0].start;
 	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
 
 	if (!tmp_ssram)
@@ -105,46 +101,82 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
 	devid = readw(ssram + SSRAM_DEVID_OFFSET);
 
 	/* Find and register and PMC telemetry entries */
-	pmc_add_pmt(pmcdev, ssram_base, ssram);
+	pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
+
+	pmc_ssram_telems[pmc_idx].devid = devid;
+	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
+
+	return 0;
+}
 
-	map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
-	if (!map)
+int pmc_ssram_telemetry_get_pmc_info(unsigned int pmc_idx,

drivers/platform/x86/intel/pmc/ssram_telemetry.c pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset) · line 122

Quoted 10 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +10 -0
+				     struct pmc_ssram_telemetry *pmc_ssram_telemetry)
+{
+	/*
+	 * PMCs are discovered in probe function. If this function is called before
+	 * probe function complete, the result would be invalid. Use device_probed
+	 * variable to avoid this case. Return -EAGAIN to inform the user to call
+	 * again later.
+	 */
+	if (!device_probed)
+		return -EAGAIN;

I'm very very skeptical this is safe. Without barriers, nothing guarantees you'll get the desired ordering. As is, device_probed could appear set before something else you depend on below this.

Quoted 72 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +35 -22
+
+	if (pmc_idx >= MAX_NUM_PMC)
+		return -EINVAL;
+
+	if (!pmc_ssram_telems || !pmc_ssram_telems[pmc_idx].devid)
 		return -ENODEV;
 
-	return pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+	pmc_ssram_telemetry->devid = pmc_ssram_telems[pmc_idx].devid;
+	pmc_ssram_telemetry->base_addr = pmc_ssram_telems[pmc_idx].base_addr;
+	return 0;
 }
+EXPORT_SYMBOL_GPL(pmc_ssram_telemetry_get_pmc_info);
 
-int pmc_core_ssram_init(struct pmc_dev *pmcdev, int func)
+static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
 {
-	struct pci_dev *pcidev;
 	int ret;
 
-	pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, func));
-	if (!pcidev)
-		return -ENODEV;
+	pmc_ssram_telems = devm_kzalloc(&pcidev->dev, sizeof(*pmc_ssram_telems) * MAX_NUM_PMC,
+					GFP_KERNEL);
+	if (!pmc_ssram_telems) {
+		ret = -ENOMEM;
+		goto probe_finish;
+	}
 
 	ret = pcim_enable_device(pcidev);
-	if (ret)
-		goto release_dev;
-
-	pmcdev->ssram_pcidev = pcidev;
+	if (ret) {
+		dev_dbg(&pcidev->dev, "failed to enable PMC SSRAM device\n");
+		goto probe_finish;
+	}
 
-	ret = pmc_core_ssram_get_pmc(pmcdev, PMC_IDX_MAIN, 0);
+	ret = pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_MAIN, 0);
 	if (ret)
-		goto disable_dev;
+		goto probe_finish;
 
-	pmc_core_ssram_get_pmc(pmcdev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
-	pmc_core_ssram_get_pmc(pmcdev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
-
-	return 0;
-
-disable_dev:
-	pmcdev->ssram_pcidev = NULL;
-	pci_disable_device(pcidev);
-release_dev:
-	pci_dev_put(pcidev);
+	pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
+	pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
 
+probe_finish:
+	device_probed = true;
 	return ret;
 }
+
+static const struct pci_device_id intel_pmc_ssram_telemetry_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, intel_pmc_ssram_telemetry_pci_ids);
+
+static struct pci_driver intel_pmc_ssram_telemetry_driver = {

drivers/platform/x86/intel/pmc/ssram_telemetry.c pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset) · line 181

Quoted 10 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +8 -1
+	.name = "intel_pmc_ssram_telemetry",
+	.id_table = intel_pmc_ssram_telemetry_pci_ids,
+	.probe = intel_pmc_ssram_telemetry_probe,
+};
+module_pci_driver(intel_pmc_ssram_telemetry_driver);
+
 MODULE_IMPORT_NS(INTEL_VSEC);
-MODULE_IMPORT_NS(INTEL_PMT_TELEMETRY);
+MODULE_AUTHOR("Xi Pardee <[email protected]>");
+MODULE_DESCRIPTION("Intel PMC SSRAM TELEMETRY driver");

Telemetry ?

drivers/platform/x86/intel/pmc/ssram_telemetry.h line 3

Quoted 10 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +1 -0
+MODULE_LICENSE("GPL");
drivers/platform/x86/intel/pmc/ssram_telemetry.h new file +3 -0
new file mode 100644
index 000000000000..938d0baf50be
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Intel PMC SSRAM TELEMETRY PCI Driver Header File

Telemetry ?

drivers/platform/x86/intel/pmc/ssram_telemetry.h line 7

Quoted 4 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.h new file +4 -0
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ * All Rights Reserved.
+ *

Extra new line.

Signature · 1 line
 i.
Quoted 39 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.h new file +38 -0
+ */
+
+#ifndef PMC_SSRAM_H
+#define PMC_SSRAM_H
+
+/**
+ * struct pmc_ssram_telemetry - Structure to keep pmc info in ssram device
+ * @devid:		device id of the pmc device
+ * @base_addr:		contains PWRM base address
+ */
+struct pmc_ssram_telemetry {
+	u16 devid;
+	u64 base_addr;
+};
+
+#if IS_REACHABLE(CONFIG_INTEL_PMC_SSRAM_TELEMETRY)
+/**
+ * pmc_ssram_telemetry_get_pmc_info() - Get a PMC devid and base_addr information
+ * @pmc_idx:               Index of the PMC
+ * @pmc_ssram_telemetry:   pmc_ssram_telemetry structure to store the PMC information
+ *
+ * Return:
+ * * 0           - Success
+ * * -EAGAIN     - Probe function has not finished yet. Try again.
+ * * -EINVAL     - Invalid pmc_idx
+ * * -ENODEV     - PMC device is not available
+ */
+int pmc_ssram_telemetry_get_pmc_info(unsigned int pmc_idx,
+				     struct pmc_ssram_telemetry *pmc_ssram_telemetry);
+#else /* !CONFIG_INTEL_PMC_SSRAM_TELEMETRY */
+static inline int pmc_ssram_telemetry_get_pmc_info(int pmc_idx,
+						   struct pmc_ssram_telemetry *pmc_ssram_telemetry)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_INTEL_PMC_SSRAM_TELEMETRY */
+
+#endif /* PMC_SSRAM_H */
author maintainer
#19 lore raw

Re: [PATCH v2 08/11] platform/x86:intel/pmc: Create Intel PMC SSRAM Telemetry driver

Hi, this email is resent because the last email was not delivered due to some HTML error.

Sorry for the inconvenience. My response is in line.

Quoted 62 lines · Ilpo Järvinen
Quoted 60 lines · Xi Pardee

Convert ssram device related functionalities to a new driver named Intel PMC SSRAM Telemetry driver. Modify PMC Core driver to use API exported by the driver to discover and achieve devid and PWRMBASE address information for each available PMC. PMC Core driver needs to get PCI device when reading from telemetry regions.

The new SSRAM driver binds to the SSRAM device and provides the following functionalities:
1. Look for and register telemetry regions available in SSRAM device.
2. Provide devid and PWRMBASE address information for the corresponding PMCs.

---
  drivers/platform/x86/intel/pmc/Kconfig        |  11 ++
  drivers/platform/x86/intel/pmc/Makefile       |   8 +-
  drivers/platform/x86/intel/pmc/arl.c          |  14 ++-
  drivers/platform/x86/intel/pmc/core.c         |  59 ++++++---
  drivers/platform/x86/intel/pmc/core.h         |   6 +-
  drivers/platform/x86/intel/pmc/mtl.c          |  14 ++-
  .../platform/x86/intel/pmc/ssram_telemetry.c  | 118 +++++++++++-------
  .../platform/x86/intel/pmc/ssram_telemetry.h  |  45 +++++++
  8 files changed, 200 insertions(+), 75 deletions(-)

create mode 100644 drivers/platform/x86/intel/pmc/ssram_telemetry.h

drivers/platform/x86/intel/pmc/Kconfig +11 -0
index d2f651fbec2c..c2ccd48fe266 100644
@@ -8,6 +8,7 @@ config INTEL_PMC_CORE
  	depends on PCI
  	depends on ACPI
  	depends on INTEL_PMT_TELEMETRY
+	depends on INTEL_PMC_SSRAM_TELEMETRY || !INTEL_PMC_SSRAM_TELEMETRY
  	help
  	  The Intel Platform Controller Hub for Intel Core SoCs provides access
  	  to Power Management Controller registers via various interfaces. This
@@ -24,3 +25,13 @@ config INTEL_PMC_CORE
  		- SLPS0 Debug registers (Cannonlake/Icelake PCH)
  		- Low Power Mode registers (Tigerlake and beyond)
  		- PMC quirks as needed to enable SLPS0/S0ix
+
+config INTEL_PMC_SSRAM_TELEMETRY
+	tristate "Intel PMC SSRAM Telemetry driver"
+	depends on INTEL_VSEC
+	help
+	  The PMC SSRAM device contains counters structured in Intel Platform
+	  Monitoring Techology (PMT) telemetry regions. This driver looks for
+	  and register these telemetry regions so they would be available for
+	  read through sysfs and Intel PMT API. The driver also provides API to
+	  expose information of PMCs available in the platform.
\ No newline at end of file
drivers/platform/x86/intel/pmc/Makefile +0 -0
index 4dd9fa93f873..e935602af2a3 100644
@@ -3,8 +3,12 @@
  # Intel x86 Platform-Specific Drivers
  #
 
Quoted 13 lines

drivers/platform/x86/intel/pmc/Makefile line 14

Quoted 12 lines
drivers/platform/x86/intel/pmc/Makefile +6 -2
-intel_pmc_core-y			:= core.o ssram_telemetry.o spt.o cnp.o \
-					   icl.o tgl.o adl.o mtl.o arl.o lnl.o
+intel_pmc_core-y			:= core.o spt.o cnp.o icl.o \
+					   tgl.o adl.o mtl.o arl.o lnl.o
  obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core.o
  intel_pmc_core_pltdrv-y			:= pltdrv.o
  obj-$(CONFIG_INTEL_PMC_CORE)		+= intel_pmc_core_pltdrv.o
+
+# Intel PMC SSRAM driver
+intel_pmc_ssram_telemetry-y		+= ssram_telemetry.o
+obj-$(CONFIG_INTEL_PMC_SSRAM_TELEMETRY)	+= intel_pmc_ssram_telemetry.o
\ No newline at end of file

Two files above are missing the last newline.

New line will be added in the next version.

Quoted 317 lines
Quoted 317 lines
drivers/platform/x86/intel/pmc/arl.c +8 -6
index 0460715c58f4..25268b1fdf97 100644
@@ -700,11 +700,13 @@ int arl_core_init(struct pmc_dev *pmcdev)
  	pmcdev->resume = arl_resume;
  	pmcdev->regmap_list = arl_pmc_info_list;
 
-	/*
-	 * If ssram init fails use legacy method to at least get the
-	 * primary PMC
-	 */
-	ret = pmc_core_ssram_init(pmcdev, func);
+	ret = pmc_core_ssram_get_reg_base(pmcdev);
+
+	/* Try again later after Intel PMC SSRAM Telemetry driver finishes probe */
+	if (ret == -EAGAIN)
+		return -EPROBE_DEFER;
+
+	/* If regbase not assigned, set map and discover using legacy method */
  	if (ret) {
  		ssram_init = false;
  		pmc->map = &arl_socs_reg_map;
@@ -718,7 +720,7 @@ int arl_core_init(struct pmc_dev *pmcdev)
  	pmc_core_punit_pmt_init(pmcdev, ARL_PMT_DMU_GUID);
 
  	if (ssram_init)	{
-		ret = pmc_core_ssram_get_lpm_reqs(pmcdev);
+		ret = pmc_core_ssram_get_lpm_reqs(pmcdev, func);
  		if (ret)
  			return ret;
  	}
drivers/platform/x86/intel/pmc/core.c +45 -14
index 8984041f35f4..19256c5570ab 100644
@@ -28,6 +28,7 @@
  #include <asm/tsc.h>
 
  #include "core.h"
+#include "ssram_telemetry.h"
  #include "../pmt/telemetry.h"
 
  /* Maximum number of modes supported by platfoms that has low power mode capability */
@@ -1613,11 +1614,12 @@ static u32 pmc_core_find_guid(struct pmc_info *list, const struct pmc_reg_map *m
  	return 0;
  }
 
-static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
+static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc, int func)
  {
  	struct telem_endpoint *ep;
  	const u8 *lpm_indices;
  	int num_maps, mode_offset = 0;
+	struct pci_dev *pcidev;
  	int ret, mode, i;
  	int lpm_size;
  	u32 guid;
@@ -1630,11 +1632,16 @@ static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
  	if (!guid)
  		return -ENXIO;
 
-	ep = pmt_telem_find_and_register_endpoint(pmcdev->ssram_pcidev, guid, 0);
+	pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, func));
+	if (!pcidev)
+		return -ENODEV;
+
+	ep = pmt_telem_find_and_register_endpoint(pcidev, guid, 0);
  	if (IS_ERR(ep)) {
  		dev_dbg(&pmcdev->pdev->dev, "couldn't get telem endpoint %ld",
  			PTR_ERR(ep));
-		return -EPROBE_DEFER;
+		ret = -EPROBE_DEFER;
+		goto release_dev;
  	}
 
  	pmc->lpm_req_regs = devm_kzalloc(&pmcdev->pdev->dev,
@@ -1710,23 +1717,22 @@ static int pmc_core_get_lpm_req(struct pmc_dev *pmcdev, struct pmc *pmc)
 
  unregister_ep:
  	pmt_telem_unregister_endpoint(ep);
+release_dev:
+	pci_dev_put(pcidev);
 
  	return ret;
  }
 
-int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev)
+int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev, int func)
  {
  	unsigned int i;
  	int ret;
 
-	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]);
+		ret = pmc_core_get_lpm_req(pmcdev, pmcdev->pmcs[i], func);
  		if (ret)
  			return ret;
  	}
@@ -1743,14 +1749,22 @@ const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
  	return NULL;
  }
 
-int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
-		     const struct pmc_reg_map *reg_map, unsigned int pmc_index)
+static int pmc_core_pmc_add(struct pmc_dev *pmcdev, unsigned int pmc_index)
  {
-	struct pmc *pmc = pmcdev->pmcs[pmc_index];
+	struct pmc_ssram_telemetry pmc_ssram_telemetry;
+	const struct pmc_reg_map *map;
+	struct pmc *pmc;
+	int ret;
+
+	ret = pmc_ssram_telemetry_get_pmc_info(pmc_index, &pmc_ssram_telemetry);
+	if (ret)
+		return ret;
 
-	if (!pwrm_base)
+	map = pmc_core_find_regmap(pmcdev->regmap_list, pmc_ssram_telemetry.devid);
+	if (!map)
  		return -ENODEV;
 
+	pmc = pmcdev->pmcs[pmc_index];
  	/* Memory for primary PMC has been allocated in core.c */
  	if (!pmc) {
  		pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL);
@@ -1758,8 +1772,8 @@ int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
  			return -ENOMEM;
  	}
 
-	pmc->map = reg_map;
-	pmc->base_addr = pwrm_base;
+	pmc->map = map;
+	pmc->base_addr = pmc_ssram_telemetry.base_addr;
  	pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length);
 
  	if (!pmc->regbase) {
@@ -1772,6 +1786,23 @@ int pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
  	return 0;
  }
 
+int pmc_core_ssram_get_reg_base(struct pmc_dev *pmcdev)
+{
+	int ret;
+
+	if (!pmcdev->regmap_list)
+		return -ENOENT;
+
+	ret = pmc_core_pmc_add(pmcdev, PMC_IDX_MAIN);
+	if (ret)
+		return ret;
+
+	pmc_core_pmc_add(pmcdev, PMC_IDX_IOE);
+	pmc_core_pmc_add(pmcdev, PMC_IDX_PCH);
+
+	return 0;
+}
+
  static const struct acpi_device_id pmc_core_acpi_ids[] = {
  	{"INT33A1", 0}, /* _HID for Intel Power Engine, _CID PNP0D80*/
  	{ }
drivers/platform/x86/intel/pmc/core.h +2 -4
index 5af1d41a83f7..2d62a71ec100 100644
@@ -594,7 +594,7 @@ extern const struct pmc_bit_map *arl_pchs_lpm_maps[];
  extern const struct pmc_reg_map arl_pchs_reg_map;
 
  extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
-extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev);
+extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev, int func);
  int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore);
 
  int pmc_core_resume_common(struct pmc_dev *pmcdev);
@@ -603,10 +603,8 @@ extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
  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, unsigned int pmc_index);
+extern int pmc_core_ssram_get_reg_base(struct pmc_dev *pmcdev);
 
  int spt_core_init(struct pmc_dev *pmcdev);
  int cnp_core_init(struct pmc_dev *pmcdev);
drivers/platform/x86/intel/pmc/mtl.c +8 -6
index e7f5b650902d..6ac52625a029 100644
@@ -1000,11 +1000,13 @@ int mtl_core_init(struct pmc_dev *pmcdev)
  	pmcdev->resume = mtl_resume;
  	pmcdev->regmap_list = mtl_pmc_info_list;
 
-	/*
-	 * If ssram init fails use legacy method to at least get the
-	 * primary PMC
-	 */
-	ret = pmc_core_ssram_init(pmcdev, func);
+	ret = pmc_core_ssram_get_reg_base(pmcdev);
+
+	/* Try again later after Intel PMC SSRAM Telemetry driver finishes probe */
+	if (ret == -EAGAIN)
+		return -EPROBE_DEFER;
+
+	/* If regbase not assigned, set map and discover using legacy method */
  	if (ret) {
  		ssram_init = false;
  		dev_warn(&pmcdev->pdev->dev,
@@ -1019,7 +1021,7 @@ int mtl_core_init(struct pmc_dev *pmcdev)
  	pmc_core_punit_pmt_init(pmcdev, MTL_PMT_DMU_GUID);
 
  	if (ssram_init)
-		return pmc_core_ssram_get_lpm_reqs(pmcdev);
+		return pmc_core_ssram_get_lpm_reqs(pmcdev, func);
 
  	return 0;
  }
drivers/platform/x86/intel/pmc/ssram_telemetry.c +20 -18
index f625d39d1aa3..1c6cc95bfefa 100644
@@ -1,20 +1,19 @@
  // SPDX-License-Identifier: GPL-2.0
  /*
- * This file contains functions to handle discovery of PMC metrics located
- * in the PMC SSRAM PCI device.
+ * Intel PMC SSRAM TELEMETRY PCI Driver
   *
   * Copyright (c) 2023, Intel Corporation.
   * All Rights Reserved.
   *
   */
 
-#include <linux/cleanup.h>
  #include <linux/pci.h>
+#include <linux/types.h>
  #include <linux/io-64-nonatomic-lo-hi.h>
 
  #include "core.h"
+#include "ssram_telemetry.h"
  #include "../vsec.h"
-#include "../pmt/telemetry.h"
 
  #define SSRAM_HDR_SIZE		0x100
  #define SSRAM_PWRM_OFFSET	0x14
@@ -24,12 +23,14 @@
  #define SSRAM_IOE_OFFSET	0x68
  #define SSRAM_DEVID_OFFSET	0x70
 
-DEFINE_FREE(pmc_core_iounmap, void __iomem *, iounmap(_T));
+static struct pmc_ssram_telemetry *pmc_ssram_telems;
+static bool device_probed;
+
+DEFINE_FREE(pmc_ssram_telemetry_iounmap, void __iomem *, iounmap(_T));
 
  static void
-pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram)
+pmc_ssram_telemetry_add_pmt(struct pci_dev *pcidev, u64 ssram_base, void __iomem *ssram)
  {
-	struct pci_dev *pcidev = pmcdev->ssram_pcidev;
  	struct intel_vsec_platform_info info = {};
  	struct intel_vsec_header *headers[2] = {};
  	struct intel_vsec_header header;
@@ -58,7 +59,7 @@ pmc_add_pmt(struct pmc_dev *pmcdev, u64 ssram_base, void __iomem *ssram)
  	info.caps = VSEC_CAP_TELEMETRY;
  	info.headers = headers;
  	info.base_addr = ssram_base;
-	info.parent = &pmcdev->pdev->dev;
+	info.parent = &pcidev->dev;
 
  	intel_vsec_register(pcidev, &info);
  }
@@ -69,19 +70,14 @@ static inline u64 get_base(void __iomem *addr, u32 offset)
  }
 
  static int
-pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
+pmc_ssram_telemetry_get_pmc(struct pci_dev *pcidev, unsigned int pmc_idx, u32 offset)
  {
-	struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
-	void __iomem __free(pmc_core_iounmap) *tmp_ssram = NULL;
-	void __iomem __free(pmc_core_iounmap) *ssram = NULL;
-	const struct pmc_reg_map *map;
+	void __iomem __free(pmc_ssram_telemetry_iounmap) * tmp_ssram = NULL;
+	void __iomem __free(pmc_ssram_telemetry_iounmap) * ssram = NULL;
  	u64 ssram_base, pwrm_base;
  	u16 devid;
 
-	if (!pmcdev->regmap_list)
-		return -ENOENT;
-
-	ssram_base = ssram_pcidev->resource[0].start;
+	ssram_base = pcidev->resource[0].start;
  	tmp_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
 
  	if (!tmp_ssram)
@@ -105,46 +101,82 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset)
  	devid = readw(ssram + SSRAM_DEVID_OFFSET);
 
  	/* Find and register and PMC telemetry entries */
-	pmc_add_pmt(pmcdev, ssram_base, ssram);
+	pmc_ssram_telemetry_add_pmt(pcidev, ssram_base, ssram);
+
+	pmc_ssram_telems[pmc_idx].devid = devid;
+	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
+
+	return 0;
+}
 
Quoted 16 lines

drivers/platform/x86/intel/pmc/ssram_telemetry.c pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset) · line 122

Quoted 13 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +11 -2
-	map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
-	if (!map)
+int pmc_ssram_telemetry_get_pmc_info(unsigned int pmc_idx,
+				     struct pmc_ssram_telemetry *pmc_ssram_telemetry)
+{
+	/*
+	 * PMCs are discovered in probe function. If this function is called before
+	 * probe function complete, the result would be invalid. Use device_probed
+	 * variable to avoid this case. Return -EAGAIN to inform the user to call
+	 * again later.
+	 */
+	if (!device_probed)
+		return -EAGAIN;

I'm very very skeptical this is safe. Without barriers, nothing guarantees you'll get the desired ordering. As is, device_probed could appear set before something else you depend on below this.

Thanks for the comments. Memory barrier should be added to ensure the correct order of load/store operation of device_probed variable.

Here is my proposed solution:
Add a write memory barrier smp_wmb right before setting device_probed to true in the intel_pmc_ssram_telemetry_probe function to ensure the store operation order. Add a read memory barrier smp_rmd after the check of device_probed in the pmc_ssram_telemetry_get_pmc_info function to ensure the load operation order.

These two barriers will ensure that the correct order of events being perceived by the consumers of this driver.

Quoted 76 lines
Quoted 76 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +38 -22
+
+	if (pmc_idx >= MAX_NUM_PMC)
+		return -EINVAL;
+
+	if (!pmc_ssram_telems || !pmc_ssram_telems[pmc_idx].devid)
  		return -ENODEV;
 
-	return pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+	pmc_ssram_telemetry->devid = pmc_ssram_telems[pmc_idx].devid;
+	pmc_ssram_telemetry->base_addr = pmc_ssram_telems[pmc_idx].base_addr;
+	return 0;
  }
+EXPORT_SYMBOL_GPL(pmc_ssram_telemetry_get_pmc_info);
 
-int pmc_core_ssram_init(struct pmc_dev *pmcdev, int func)
+static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
  {
-	struct pci_dev *pcidev;
  	int ret;
 
-	pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, func));
-	if (!pcidev)
-		return -ENODEV;
+	pmc_ssram_telems = devm_kzalloc(&pcidev->dev, sizeof(*pmc_ssram_telems) * MAX_NUM_PMC,
+					GFP_KERNEL);
+	if (!pmc_ssram_telems) {
+		ret = -ENOMEM;
+		goto probe_finish;
+	}
 
  	ret = pcim_enable_device(pcidev);
-	if (ret)
-		goto release_dev;
-
-	pmcdev->ssram_pcidev = pcidev;
+	if (ret) {
+		dev_dbg(&pcidev->dev, "failed to enable PMC SSRAM device\n");
+		goto probe_finish;
+	}
 
-	ret = pmc_core_ssram_get_pmc(pmcdev, PMC_IDX_MAIN, 0);
+	ret = pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_MAIN, 0);
  	if (ret)
-		goto disable_dev;
+		goto probe_finish;
 
-	pmc_core_ssram_get_pmc(pmcdev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
-	pmc_core_ssram_get_pmc(pmcdev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
-
-	return 0;
-
-disable_dev:
-	pmcdev->ssram_pcidev = NULL;
-	pci_disable_device(pcidev);
-release_dev:
-	pci_dev_put(pcidev);
+	pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
+	pmc_ssram_telemetry_get_pmc(pcidev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
 
+probe_finish:
+	device_probed = true;
  	return ret;
  }
+
+static const struct pci_device_id intel_pmc_ssram_telemetry_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, intel_pmc_ssram_telemetry_pci_ids);
+
+static struct pci_driver intel_pmc_ssram_telemetry_driver = {
+	.name = "intel_pmc_ssram_telemetry",
+	.id_table = intel_pmc_ssram_telemetry_pci_ids,
+	.probe = intel_pmc_ssram_telemetry_probe,
Quoted 8 lines

drivers/platform/x86/intel/pmc/ssram_telemetry.c pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, unsigned int pmc_idx, u32 offset) · line 181

Quoted 7 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +5 -1
+};
+module_pci_driver(intel_pmc_ssram_telemetry_driver);
+
  MODULE_IMPORT_NS(INTEL_VSEC);
-MODULE_IMPORT_NS(INTEL_PMT_TELEMETRY);
+MODULE_AUTHOR("Xi Pardee <[email protected]>");
+MODULE_DESCRIPTION("Intel PMC SSRAM TELEMETRY driver");

Telemetry ?

Will change in next version.

Quoted 12 lines

drivers/platform/x86/intel/pmc/ssram_telemetry.h line 3

Quoted 11 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +1 -0
+MODULE_LICENSE("GPL");
drivers/platform/x86/intel/pmc/ssram_telemetry.h new file +3 -0
new file mode 100644
index 000000000000..938d0baf50be
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Intel PMC SSRAM TELEMETRY PCI Driver Header File

Telemetry ?

Will change in next version.

Quoted 6 lines

drivers/platform/x86/intel/pmc/ssram_telemetry.h line 7

Quoted 5 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.h new file +4 -0
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ * All Rights Reserved.
+ *

Extra new line.

Will remove in next version.

Thanks!

Xi

Quoted 1 line
author maintainer
#20 lore raw

PATCH v2 9/11 platform/x86:intel/pmc: Add Lunar Lake SSRAM devid

In reply to Xi Pardee

Enable SSRAM device Lunar Lake support by adding Lunar Lake SSRAM devid to Intel SSRAM Telemetry driver.

---
 drivers/platform/x86/intel/pmc/core.h            | 3 +++
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 1 +
 2 files changed, 4 insertions(+)
drivers/platform/x86/intel/pmc/core.h +3 -0
index 2d62a71ec100..25974f9d329e 100644
@@ -300,6 +300,9 @@ enum ppfear_regs {
 #define PMC_DEVID_MTL_IOEP	0x7ecf
 #define PMC_DEVID_MTL_IOEM	0x7ebf
 
+/* LNL */
+#define PMC_DEVID_LNL_SOCM	0xa87f
+
 extern const char *pmc_lpm_modes[];
 
 struct pmc_bit_map {
drivers/platform/x86/intel/pmc/ssram_telemetry.c +1 -0
index 1c6cc95bfefa..025013b051c7 100644
@@ -165,6 +165,7 @@ static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct
 static const struct pci_device_id intel_pmc_ssram_telemetry_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_LNL_SOCM) },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, intel_pmc_ssram_telemetry_pci_ids);
Signature · 1 line
2.43.0
maintainer Reviewed-by on v2 9/11
#21 lore raw

Re: [PATCH v2 09/11] platform/x86:intel/pmc: Add Lunar Lake SSRAM devid

Quoted 29 lines · Xi Pardee

Enable SSRAM device Lunar Lake support by adding Lunar Lake SSRAM devid to Intel SSRAM Telemetry driver.

---
 drivers/platform/x86/intel/pmc/core.h            | 3 +++
 drivers/platform/x86/intel/pmc/ssram_telemetry.c | 1 +
 2 files changed, 4 insertions(+)
drivers/platform/x86/intel/pmc/core.h +3 -0
index 2d62a71ec100..25974f9d329e 100644
@@ -300,6 +300,9 @@ enum ppfear_regs {
 #define PMC_DEVID_MTL_IOEP	0x7ecf
 #define PMC_DEVID_MTL_IOEM	0x7ebf
 
+/* LNL */
+#define PMC_DEVID_LNL_SOCM	0xa87f
+
 extern const char *pmc_lpm_modes[];
 
 struct pmc_bit_map {
drivers/platform/x86/intel/pmc/ssram_telemetry.c +0 -0
index 1c6cc95bfefa..025013b051c7 100644

drivers/platform/x86/intel/pmc/ssram_telemetry.c static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct · line 171

Quoted 7 lines
drivers/platform/x86/intel/pmc/ssram_telemetry.c +1 -0
@@ -165,6 +165,7 @@ static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pcidev, const struct
 static const struct pci_device_id intel_pmc_ssram_telemetry_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_LNL_SOCM) },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, intel_pmc_ssram_telemetry_pci_ids);
Signature · 1 line
 i.
author maintainer
#22 lore raw

PATCH v2 10/11 platform/x86:intel/pmt: Get PMC from SSRAM for Lunar Lake

In reply to Xi Pardee

Add support to discover and achieve PMC information from Intel SSRAM Telemetry driver for Lunar Lake platforms.

---
 drivers/platform/x86/intel/pmc/lnl.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)
drivers/platform/x86/intel/pmc/lnl.c +22 -4
index e7a8077d1a3e..109b08d43fc8 100644
@@ -13,6 +13,14 @@
 
 #include "core.h"
 
+static struct pmc_info lnl_pmc_info_list[] = {
+	{
+		.devid	= PMC_DEVID_LNL_SOCM,
+		.map	= &lnl_socm_reg_map,
+	},
+	{}
+};
+
 const struct pmc_bit_map lnl_ltr_show_map[] = {
 	{"SOUTHPORT_A",		CNP_PMC_LTR_SPA},
 	{"SOUTHPORT_B",		CNP_PMC_LTR_SPB},
@@ -561,10 +569,20 @@ int lnl_core_init(struct pmc_dev *pmcdev)
 	pmcdev->suspend = cnl_suspend;
 	pmcdev->resume = lnl_resume;
 
-	pmc->map = &lnl_socm_reg_map;
-	ret = get_primary_reg_base(pmc);
-	if (ret)
-		return ret;
+	pmcdev->regmap_list = lnl_pmc_info_list;
+	ret = pmc_core_ssram_get_reg_base(pmcdev);
+
+	/* Try again later after Intel PMC SSRAM Telemetry driver finishes probe */
+	if (ret == -EAGAIN)
+		return -EPROBE_DEFER;
+
+	/* If regbase not assigned, set map and discover using legacy method */
+	if (ret) {
+		pmc->map = &lnl_socm_reg_map;
+		ret = get_primary_reg_base(pmc);
+		if (ret)
+			return ret;
+	}
 
 	pmc_core_get_low_power_modes(pmcdev);
 
Signature · 1 line
2.43.0
author maintainer
#23 lore raw

PATCH v2 11/11 platform/x86:intel/pmc: Get LPM information for Lunar Lake

In reply to Xi Pardee

Add support to find and read the requirements from the telemetry entries for Lunar Lake platforms.

---
 drivers/platform/x86/intel/pmc/lnl.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/platform/x86/intel/pmc/lnl.c +15 -0
index 109b08d43fc8..f5fee9e105e2 100644
@@ -13,8 +13,13 @@
 
 #include "core.h"
 
+#define SOCM_LPM_REQ_GUID	0x15099748
+
+static const u8 LNL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
+
 static struct pmc_info lnl_pmc_info_list[] = {
 	{
+		.guid	= SOCM_LPM_REQ_GUID,
 		.devid	= PMC_DEVID_LNL_SOCM,
 		.map	= &lnl_socm_reg_map,
 	},
@@ -536,6 +541,7 @@ const struct pmc_reg_map lnl_socm_reg_map = {
 	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
 	.s0ix_blocker_maps = lnl_blk_maps,
 	.s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET,
+	.lpm_reg_index = LNL_LPM_REG_INDEX,
 };
 
 #define LNL_NPU_PCI_DEV		0x643e
@@ -561,6 +567,8 @@ static int lnl_resume(struct pmc_dev *pmcdev)
 
 int lnl_core_init(struct pmc_dev *pmcdev)
 {
+	bool ssram_init = true;
+	int func = 2;
 	int ret;
 	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
 
@@ -578,6 +586,7 @@ int lnl_core_init(struct pmc_dev *pmcdev)
 
 	/* If regbase not assigned, set map and discover using legacy method */
 	if (ret) {
+		ssram_init = false;
 		pmc->map = &lnl_socm_reg_map;
 		ret = get_primary_reg_base(pmc);
 		if (ret)
@@ -586,5 +595,11 @@ int lnl_core_init(struct pmc_dev *pmcdev)
 
 	pmc_core_get_low_power_modes(pmcdev);
 
+	if (ssram_init)	{
+		ret = pmc_core_ssram_get_lpm_reqs(pmcdev, func);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
Signature · 1 line
2.43.0
maintainer
#24 lore raw

Re: [PATCH v2 11/11] platform/x86:intel/pmc: Get LPM information for Lunar Lake

Quoted 52 lines · Xi Pardee

Add support to find and read the requirements from the telemetry entries for Lunar Lake platforms.

---
 drivers/platform/x86/intel/pmc/lnl.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/platform/x86/intel/pmc/lnl.c +9 -0
index 109b08d43fc8..f5fee9e105e2 100644
@@ -13,8 +13,13 @@
 
 #include "core.h"
 
+#define SOCM_LPM_REQ_GUID	0x15099748
+
+static const u8 LNL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
+
 static struct pmc_info lnl_pmc_info_list[] = {
 	{
+		.guid	= SOCM_LPM_REQ_GUID,
 		.devid	= PMC_DEVID_LNL_SOCM,
 		.map	= &lnl_socm_reg_map,
 	},
@@ -536,6 +541,7 @@ const struct pmc_reg_map lnl_socm_reg_map = {
 	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
 	.s0ix_blocker_maps = lnl_blk_maps,
 	.s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET,
+	.lpm_reg_index = LNL_LPM_REG_INDEX,
 };
 
 #define LNL_NPU_PCI_DEV		0x643e
@@ -561,6 +567,8 @@ static int lnl_resume(struct pmc_dev *pmcdev)
 
 int lnl_core_init(struct pmc_dev *pmcdev)
 {
+	bool ssram_init = true;
+	int func = 2;
 	int ret;
 	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
 
@@ -578,6 +586,7 @@ int lnl_core_init(struct pmc_dev *pmcdev)
 
 	/* If regbase not assigned, set map and discover using legacy method */
 	if (ret) {
+		ssram_init = false;
 		pmc->map = &lnl_socm_reg_map;
 		ret = get_primary_reg_base(pmc);
 		if (ret)

drivers/platform/x86/intel/pmc/lnl.c int lnl_core_init(struct pmc_dev *pmcdev) · line 601

Quoted 7 lines
drivers/platform/x86/intel/pmc/lnl.c +4 -0
@@ -586,5 +595,11 @@ int lnl_core_init(struct pmc_dev *pmcdev)
 
 	pmc_core_get_low_power_modes(pmcdev);
 
+	if (ssram_init)	{
+		ret = pmc_core_ssram_get_lpm_reqs(pmcdev, func);
+		if (ret)
+			return ret;

There's quite much duplication related to this legacy/ssram init in the per arch core init functions. And some inconsistencies too which seem incidental such as mtl.c using return directly here.

Signature · 1 line
 i.
author maintainer
#25 lore raw

Re: [PATCH v2 11/11] platform/x86:intel/pmc: Get LPM information for Lunar Lake

Quoted 57 lines · Ilpo Järvinen
Quoted 55 lines · Xi Pardee

Add support to find and read the requirements from the telemetry entries for Lunar Lake platforms.

---
  drivers/platform/x86/intel/pmc/lnl.c | 15 +++++++++++++++
  1 file changed, 15 insertions(+)
drivers/platform/x86/intel/pmc/lnl.c +9 -0
index 109b08d43fc8..f5fee9e105e2 100644
@@ -13,8 +13,13 @@
 
  #include "core.h"
 
+#define SOCM_LPM_REQ_GUID	0x15099748
+
+static const u8 LNL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
+
  static struct pmc_info lnl_pmc_info_list[] = {
  	{
+		.guid	= SOCM_LPM_REQ_GUID,
  		.devid	= PMC_DEVID_LNL_SOCM,
  		.map	= &lnl_socm_reg_map,
  	},
@@ -536,6 +541,7 @@ const struct pmc_reg_map lnl_socm_reg_map = {
  	.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
  	.s0ix_blocker_maps = lnl_blk_maps,
  	.s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET,
+	.lpm_reg_index = LNL_LPM_REG_INDEX,
  };
 
  #define LNL_NPU_PCI_DEV		0x643e
@@ -561,6 +567,8 @@ static int lnl_resume(struct pmc_dev *pmcdev)
 
  int lnl_core_init(struct pmc_dev *pmcdev)
  {
+	bool ssram_init = true;
+	int func = 2;
  	int ret;
  	struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
 
@@ -578,6 +586,7 @@ int lnl_core_init(struct pmc_dev *pmcdev)
 
  	/* If regbase not assigned, set map and discover using legacy method */
  	if (ret) {
+		ssram_init = false;
  		pmc->map = &lnl_socm_reg_map;
  		ret = get_primary_reg_base(pmc);
  		if (ret)
@@ -586,5 +595,11 @@ int lnl_core_init(struct pmc_dev *pmcdev)
 
  	pmc_core_get_low_power_modes(pmcdev);
 
Quoted 7 lines

drivers/platform/x86/intel/pmc/lnl.c int lnl_core_init(struct pmc_dev *pmcdev) · line 601

Quoted 4 lines
drivers/platform/x86/intel/pmc/lnl.c +4 -0
+	if (ssram_init)	{
+		ret = pmc_core_ssram_get_lpm_reqs(pmcdev, func);
+		if (ret)
+			return ret;

There's quite much duplication related to this legacy/ssram init in the per arch core init functions. And some inconsistencies too which seem incidental such as mtl.c using return directly here.

I will try to extract the duplicate code to a common function and remove the inconsistencies between different architecture in next version.

Xi