All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xi Pardee <xi.pardee@linux.intel.com>
To: xi.pardee@linux.intel.com, irenic.rajneesh@gmail.com,
	david.e.box@linux.intel.com, hdegoede@redhat.com,
	ilpo.jarvinen@linux.intel.com,
	platform-driver-x86@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 2/7] platform/x86:intel/pmc: Create Intel PMC SSRAM Telemetry driver
Date: Fri,  9 Aug 2024 13:46:31 -0700	[thread overview]
Message-ID: <20240809204648.1124545-3-xi.pardee@linux.intel.com> (raw)
In-Reply-To: <20240809204648.1124545-1-xi.pardee@linux.intel.com>

From: Xi Pardee <xi.pardee@intel.com>

Create Intel PMC SSRAM Telemetry driver for SSRAM device. The driver binds
to 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.

Signed-off-by: Xi Pardee <xi.pardee@intel.com>
---
 drivers/platform/x86/intel/pmc/Kconfig        |  10 +
 drivers/platform/x86/intel/pmc/Makefile       |   4 +
 drivers/platform/x86/intel/pmc/core.h         |  10 +
 .../platform/x86/intel/pmc/ssram_telemetry.c  | 184 ++++++++++++++++++
 .../platform/x86/intel/pmc/ssram_telemetry.h  |  45 +++++
 5 files changed, 253 insertions(+)
 create mode 100644 drivers/platform/x86/intel/pmc/ssram_telemetry.c
 create mode 100644 drivers/platform/x86/intel/pmc/ssram_telemetry.h

diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
index d2f651fbec2c..fe33348cd7e2 100644
--- a/drivers/platform/x86/intel/pmc/Kconfig
+++ b/drivers/platform/x86/intel/pmc/Kconfig
@@ -24,3 +24,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.
diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile
index 6b682be0ec5a..8352c6d66f2b 100644
--- a/drivers/platform/x86/intel/pmc/Makefile
+++ b/drivers/platform/x86/intel/pmc/Makefile
@@ -8,3 +8,7 @@ intel_pmc_core-y			:= core.o spt.o cnp.o icl.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
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index b0c66df8cd98..1e5726745394 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -285,6 +285,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
+
+/* MTL */
+#define PMC_DEVID_MTL_SOCM	0x7e7f
+
+/* LNL */
+#define PMC_DEVID_LNL_SOCM	0xa87f
+
 extern const char *pmc_lpm_modes[];
 
 struct pmc_bit_map {
diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.c b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
new file mode 100644
index 000000000000..25f6e07c15be
--- /dev/null
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel PMC SSRAM TELEMETRY PCI Driver
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ * All Rights Reserved.
+ *
+ */
+
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include "../vsec.h"
+#include "core.h"
+#include "ssram_telemetry.h"
+
+#define SSRAM_HDR_SIZE		0x100
+#define SSRAM_PWRM_OFFSET	0x14
+#define SSRAM_DVSEC_OFFSET	0x1C
+#define SSRAM_DVSEC_SIZE	0x10
+#define SSRAM_PCH_OFFSET	0x60
+#define SSRAM_IOE_OFFSET	0x68
+#define SSRAM_DEVID_OFFSET	0x70
+
+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_ssram_telemetry_add_pmt(struct pci_dev *pdev, u64 ssram_base, void __iomem *ssram)
+{
+	struct intel_vsec_platform_info info = {};
+	struct intel_vsec_header *headers[2] = {};
+	struct intel_vsec_header header;
+	void __iomem *dvsec;
+	u32 dvsec_offset;
+	u32 table, hdr;
+
+	dvsec_offset = readl(ssram + SSRAM_DVSEC_OFFSET);
+	dvsec = ioremap(ssram_base + dvsec_offset, SSRAM_DVSEC_SIZE);
+	if (!dvsec)
+		return;
+
+	hdr = readl(dvsec + PCI_DVSEC_HEADER1);
+	header.id = readw(dvsec + PCI_DVSEC_HEADER2);
+	header.rev = PCI_DVSEC_HEADER1_REV(hdr);
+	header.length = PCI_DVSEC_HEADER1_LEN(hdr);
+	header.num_entries = readb(dvsec + INTEL_DVSEC_ENTRIES);
+	header.entry_size = readb(dvsec + INTEL_DVSEC_SIZE);
+
+	table = readl(dvsec + INTEL_DVSEC_TABLE);
+	header.tbir = INTEL_DVSEC_TABLE_BAR(table);
+	header.offset = INTEL_DVSEC_TABLE_OFFSET(table);
+	iounmap(dvsec);
+
+	headers[0] = &header;
+	info.caps = VSEC_CAP_TELEMETRY;
+	info.headers = headers;
+	info.base_addr = ssram_base;
+	info.parent = &pdev->dev;
+
+	intel_vsec_register(pdev, &info);
+}
+
+static inline u64 get_base(void __iomem *addr, u32 offset)
+{
+	return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3);
+}
+
+static int pmc_ssram_telemetry_get_pmc(struct pci_dev *pdev, unsigned int pmc_idx, u32 offset)
+{
+	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;
+
+	ssram_base = pdev->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)
+		 * are read from fixed offsets in MMIO of the primary PMC BAR.
+		 */
+		ssram_base = get_base(tmp_ssram, offset);
+		if (!ssram_base)
+			return -ENODEV;
+
+		ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+		if (!ssram)
+			return -ENOMEM;
+	} else
+		ssram = no_free_ptr(tmp_ssram);
+
+	/* Find and register and PMC telemetry entries */
+	pmc_ssram_telemetry_add_pmt(pdev, ssram_base, ssram);
+
+	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
+	if (!pwrm_base)
+		return -ENODEV;
+	devid = readw(ssram + SSRAM_DEVID_OFFSET);
+
+	pmc_ssram_telems[pmc_idx].devid = devid;
+	pmc_ssram_telems[pmc_idx].base_addr = pwrm_base;
+
+	return 0;
+}
+
+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;
+
+	if (pmc_idx >= MAX_NUM_PMC)
+		return -EINVAL;
+
+	if (!pmc_ssram_telems || !pmc_ssram_telems[pmc_idx].devid)
+		return -ENODEV;
+
+	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);
+
+static int intel_pmc_ssram_telemetry_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int ret;
+
+	pmc_ssram_telems = devm_kzalloc(&pdev->dev, sizeof(*pmc_ssram_telems) * MAX_NUM_PMC,
+					GFP_KERNEL);
+	if (!pmc_ssram_telems) {
+		ret = -ENOMEM;
+		goto probe_finish;
+	}
+
+	ret = pcim_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev, "failed to enable PMC SSRAM device\n");
+		goto probe_finish;
+	}
+
+	ret = pmc_ssram_telemetry_get_pmc(pdev, PMC_IDX_MAIN, 0);
+	if (ret)
+		goto probe_finish;
+
+	pmc_ssram_telemetry_get_pmc(pdev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
+	pmc_ssram_telemetry_get_pmc(pdev, 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_LNL_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,
+};
+module_pci_driver(intel_pmc_ssram_telemetry_driver);
+
+MODULE_IMPORT_NS(INTEL_VSEC);
+MODULE_AUTHOR("Xi Pardee <xi.pardee@intel.com>");
+MODULE_DESCRIPTION("Intel PMC SSRAM TELEMETRY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/pmc/ssram_telemetry.h b/drivers/platform/x86/intel/pmc/ssram_telemetry.h
new file mode 100644
index 000000000000..938d0baf50be
--- /dev/null
+++ b/drivers/platform/x86/intel/pmc/ssram_telemetry.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Intel PMC SSRAM TELEMETRY PCI Driver Header File
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ * All Rights Reserved.
+ *
+ */
+
+#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 */
-- 
2.43.0


  parent reply	other threads:[~2024-08-09 20:46 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-09 20:46 [PATCH 0/7] Create Intel PMC SSRAM Telemetry driver Xi Pardee
2024-08-09 20:46 ` [PATCH 1/7] platform/x86:intel/pmc: Remove SSRAM support from PMC Core Xi Pardee
2024-08-09 20:46 ` Xi Pardee [this message]
2024-08-12 10:40   ` [PATCH 2/7] platform/x86:intel/pmc: Create Intel PMC SSRAM Telemetry driver kernel test robot
2024-08-09 20:46 ` [PATCH 3/7] platform/x86:intel/pmc: Add support to get PMC information from SSRAM Xi Pardee
2024-08-09 20:46 ` [PATCH 4/7] platform/x86:intel/pmt: Get PMC from SSRAM for available platforms Xi Pardee
2024-08-09 20:46 ` [PATCH 5/7] platform/x86:intel/pmt: Create inline version for telemetry functions Xi Pardee
2024-08-09 20:46 ` [PATCH 6/7] platform/x86:intel/pmc: Add support to Retrieve LPM information Xi Pardee
2024-08-18  3:27   ` kernel test robot
2024-08-09 20:46 ` [PATCH 7/7] platform/x86:intel/pmc: Get LPM information for available platforms Xi Pardee
2024-08-13 16:01 ` [PATCH 0/7] Create Intel PMC SSRAM Telemetry driver Ilpo Järvinen
2024-08-13 23:01   ` Xi Pardee

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=20240809204648.1124545-3-xi.pardee@linux.intel.com \
    --to=xi.pardee@linux.intel.com \
    --cc=david.e.box@linux.intel.com \
    --cc=hdegoede@redhat.com \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=irenic.rajneesh@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    /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.