From: "David E. Box" <david.e.box@linux.intel.com>
To: linux-kernel@vger.kernel.org,
platform-driver-x86@vger.kernel.org,
ilpo.jarvinen@linux.intel.com, rajvi.jingar@linux.intel.com
Subject: [PATCH V3 13/16] platform/x86/intel/pmc: Retrieve LPM information using Intel PMT
Date: Wed, 11 Oct 2023 19:38:37 -0700 [thread overview]
Message-ID: <20231012023840.3845703-14-david.e.box@linux.intel.com> (raw)
In-Reply-To: <20231012023840.3845703-1-david.e.box@linux.intel.com>
From: Xi Pardee <xi.pardee@intel.com>
On supported platforms, the low power mode (LPM) requirements for entering
each idle substate are described in Platform Monitoring Technology (PMT)
telemetry entries. Provide a function for platform code to attempt to find
and read the requirements from the telemetry entries.
Signed-off-by: Xi Pardee <xi.pardee@intel.com>
Signed-off-by: David E. Box <david.e.box@linux.intel.com>
---
V3 - no change
V2 - remove extra parens
drivers/platform/x86/intel/pmc/core.h | 3 +
drivers/platform/x86/intel/pmc/core_ssram.c | 135 ++++++++++++++++++++
2 files changed, 138 insertions(+)
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index edaa70067e41..85b6f6ae4995 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -320,6 +320,7 @@ struct pmc_reg_map {
const u32 lpm_status_offset;
const u32 lpm_live_status_offset;
const u32 etr3_offset;
+ const u8 *lpm_reg_index;
};
/**
@@ -329,6 +330,7 @@ struct pmc_reg_map {
* specific attributes
*/
struct pmc_info {
+ u32 guid;
u16 devid;
const struct pmc_reg_map *map;
};
@@ -486,6 +488,7 @@ extern const struct pmc_bit_map *mtl_ioem_lpm_maps[];
extern const struct pmc_reg_map mtl_ioem_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_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value);
int pmc_core_resume_common(struct pmc_dev *pmcdev);
diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c
index 1ecfa3804117..8cd5bc4e77f6 100644
--- a/drivers/platform/x86/intel/pmc/core_ssram.c
+++ b/drivers/platform/x86/intel/pmc/core_ssram.c
@@ -26,6 +26,140 @@
DEFINE_FREE(pmc_core_iounmap, void __iomem *, iounmap(_T));
+/* PCH query */
+#define LPM_HEADER_OFFSET 1
+#define LPM_REG_COUNT 28
+#define LPM_MODE_OFFSET 1
+
+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)
{
@@ -217,3 +351,4 @@ int pmc_core_ssram_init(struct pmc_dev *pmcdev)
return ret;
}
MODULE_IMPORT_NS(INTEL_VSEC);
+MODULE_IMPORT_NS(INTEL_PMT_TELEMETRY);
--
2.34.1
next prev parent reply other threads:[~2023-10-12 2:39 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-12 2:38 [PATCH V3 00/16] intel_pmc: Add telemetry API to read counters David E. Box
2023-10-12 2:38 ` [PATCH V3 01/16] platform/x86/intel/vsec: Move structures to header David E. Box
2023-10-12 2:38 ` [PATCH V3 02/16] platform/x86/intel/vsec: remove platform_info from vsec device structure David E. Box
2023-10-12 15:31 ` Ilpo Järvinen
2023-10-12 16:55 ` David E. Box
2023-10-12 2:38 ` [PATCH V3 03/16] platform/x86/intel/vsec: Use cleanup.h David E. Box
2023-10-12 5:25 ` kernel test robot
2023-10-12 17:23 ` David E. Box
2023-10-13 10:39 ` Ilpo Järvinen
2023-10-13 18:14 ` Joe Perches
2023-10-24 5:15 ` Joe Perches
2023-10-12 5:48 ` kernel test robot
2023-10-12 14:46 ` Ilpo Järvinen
2023-10-12 17:13 ` David E. Box
2023-10-13 10:54 ` Ilpo Järvinen
2023-10-13 22:16 ` David E. Box
2023-10-16 12:02 ` Ilpo Järvinen
2023-10-12 2:38 ` [PATCH V3 04/16] platform/x86/intel/vsec: Add intel_vsec_register David E. Box
2023-10-12 5:48 ` kernel test robot
2023-10-12 2:38 ` [PATCH V3 05/16] platform/x86/intel/vsec: Add base address field David E. Box
2023-10-12 2:38 ` [PATCH V3 06/16] platform/x86/intel/pmt: Add header to struct intel_pmt_entry David E. Box
2023-10-12 2:38 ` [PATCH V3 07/16] platform/x86/intel/pmt: telemetry: Export API to read telemetry David E. Box
2023-10-12 2:38 ` [PATCH V3 08/16] platform/x86:intel/pmc: Call pmc_get_low_power_modes from platform init David E. Box
2023-10-12 2:38 ` [PATCH V3 09/16] platform/x86/intel/pmc: Allow pmc_core_ssram_init to fail David E. Box
2023-10-12 15:01 ` Ilpo Järvinen
2023-10-12 17:52 ` David E. Box
2023-10-13 11:36 ` Ilpo Järvinen
2023-10-12 2:38 ` [PATCH V3 10/16] platform/x86/intel/pmc: Split pmc_core_ssram_get_pmc() David E. Box
2023-10-12 6:09 ` kernel test robot
2023-10-12 15:14 ` Ilpo Järvinen
2023-10-12 17:28 ` David E. Box
2023-10-12 2:38 ` [PATCH V3 11/16] platform/x86/intel/pmc: Find and register PMC telemetry entries David E. Box
2023-10-12 15:17 ` Ilpo Järvinen
2023-10-12 2:38 ` [PATCH V3 12/16] platform/x86/intel/pmc: Display LPM requirements for multiple PMCs David E. Box
2023-10-12 2:38 ` David E. Box [this message]
2023-10-12 2:38 ` [PATCH V3 14/16] platform/x86/intel/pmc: Read low power mode requirements for MTL-M and MTL-P David E. Box
2023-10-12 2:38 ` [PATCH V3 15/16] platform/x86/intel/pmc: Add debug attribute for Die C6 counter David E. Box
2023-10-12 2:38 ` [PATCH V3 16/16] platform/x86/intel/pmc: Show Die C6 counter on Meteor Lake David E. Box
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231012023840.3845703-14-david.e.box@linux.intel.com \
--to=david.e.box@linux.intel.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=platform-driver-x86@vger.kernel.org \
--cc=rajvi.jingar@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.