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: David E. Box <david.e.box@xxxxxxxxxxxxxxx> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx> --- V4 - no change V3 - no change V2 - no change drivers/platform/x86/intel/pmc/Kconfig | 1 + drivers/platform/x86/intel/pmc/core_ssram.c | 52 +++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig index b526597e4deb..d2f651fbec2c 100644 --- a/drivers/platform/x86/intel/pmc/Kconfig +++ b/drivers/platform/x86/intel/pmc/Kconfig @@ -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 diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c index ccb3748dbed9..936aa0d5f452 100644 --- a/drivers/platform/x86/intel/pmc/core_ssram.c +++ b/drivers/platform/x86/intel/pmc/core_ssram.c @@ -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 @@ -22,6 +24,49 @@ #define SSRAM_IOE_OFFSET 0x68 #define SSRAM_DEVID_OFFSET 0x70 +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) @@ -96,6 +141,9 @@ pmc_core_get_secondary_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset) pwrm_base = get_base(secondary_ssram, SSRAM_PWRM_OFFSET); devid = readw(secondary_ssram + SSRAM_DEVID_OFFSET); + /* Find and register and PMC telemetry entries */ + pmc_add_pmt(pmcdev, ssram_base, main_ssram); + map = pmc_core_find_regmap(pmcdev->regmap_list, devid); if (!map) return -ENODEV; @@ -124,6 +172,9 @@ pmc_core_get_primary_pmc(struct pmc_dev *pmcdev) 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; @@ -163,3 +214,4 @@ int pmc_core_ssram_init(struct pmc_dev *pmcdev) return ret; } +MODULE_IMPORT_NS(INTEL_VSEC); -- 2.34.1