Commit 104f7494 authored by David E. Box's avatar David E. Box Committed by Hans de Goede
Browse files

platform/x86/intel/pmc: Find and register PMC telemetry entries



The PMC SSRAM device contains counters that are structured in Intel
Platform Monitoring Technology (PMT) telemetry regions. Look for and
register these telemetry regions from the driver so that they may be read
using the Intel PMT ABI.

Signed-off-by: default avatarDavid E. Box <david.e.box@linux.intel.com>
Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20231129222132.2331261-16-david.e.box@linux.intel.com


Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 642dd26f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ config INTEL_PMC_CORE
	tristate "Intel PMC Core driver"
	depends on PCI
	depends on ACPI
	depends on INTEL_PMT_TELEMETRY
	help
	  The Intel Platform Controller Hub for Intel Core SoCs provides access
	  to Power Management Controller registers via various interfaces. This
+49 −0
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@
#include <linux/io-64-nonatomic-lo-hi.h>

#include "core.h"
#include "../vsec.h"
#include "../pmt/telemetry.h"

#define SSRAM_HDR_SIZE		0x100
#define SSRAM_PWRM_OFFSET	0x14
@@ -24,6 +26,49 @@

DEFINE_FREE(pmc_core_iounmap, void __iomem *, iounmap(_T));

static void
pmc_add_pmt(struct pmc_dev *pmcdev, 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;
	void __iomem *dvsec;
	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;

	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 = &pmcdev->pdev->dev;

	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)
@@ -101,6 +146,9 @@ pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset)
	pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
	devid = readw(ssram + SSRAM_DEVID_OFFSET);

	/* Find and register and PMC telemetry entries */
	pmc_add_pmt(pmcdev, ssram_base, ssram);

	map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
	if (!map)
		return -ENODEV;
@@ -140,3 +188,4 @@ int pmc_core_ssram_init(struct pmc_dev *pmcdev)

	return ret;
}
MODULE_IMPORT_NS(INTEL_VSEC);