2023-02-02 01:09:09

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 0/7] Add TPMI support

The TPMI (Topology Aware Register and PM Capsule Interface) provides a
flexible, extendable and PCIe enumerable MMIO interface for PM features.

For example Intel Speed Select Technology (Intel SST) can replace all
mailbox commands with direct MMIO access. This reduces latency for
SST commands and also defines an architectural interface which will
persist for several next generations.

Also Intel RAPL (Running Average Power Limit) provides a MMIO
interface using TPMI. This has advantage over traditional MSR
(Model Specific Register) interface, where a thread needs to be scheduled
on the target CPU to read or write. Also the RAPL features vary between
CPU models, and hence lot of model specific code. Here TPMI provides an
architectural interface by providing hierarchical tables and fields,
which will not need any model specific implementation.

Same value is for Intel Uncore frequency where MSR interface can't
be used because of multiple domains.

The TPMI interface uses a PCI VSEC structure to expose the location of
MMIO region, which is handled by Intel VSEC driver. Intel VSEC driver is
already present in upstream kernel.

This series contains the base driver, which parses TPMI MMIO region
and creates device nodes for supported features. The current set of
PM feature support includes, Intel Speed Select, RAPL, Uncore frequency
scaling.

The first there patches updates Intel VSEC driver to add TPMI VSEC ID
and enhance to reuse the code.
The next three patches adds TPMI base driver support.
The last patch adds MAINTAINERS entry.

The TPMI documentation can be downloaded from:
https://github.com/intel/tpmi_power_management

This series cleanly applies on 6.2-rc1.

Srinivas Pandruvada (7):
platform/x86/intel/vsec: Add TPMI ID
platform/x86/intel/vsec: Enhance and Export intel_vsec_add_aux()
platform/x86/intel/vsec: Support private data
platform/x86/intel: Intel TPMI enumeration driver
platform/x86/intel/tpmi: Process CPU package mapping
platform/x86/intel/tpmi: ADD tpmi external interface for tpmi feature
drivers
MAINTAINERS: Add entry for TPMI driver

MAINTAINERS | 6 +
drivers/platform/x86/intel/Kconfig | 13 +
drivers/platform/x86/intel/Makefile | 4 +
drivers/platform/x86/intel/tpmi.c | 415 ++++++++++++++++++++++++++++
drivers/platform/x86/intel/vsec.c | 21 +-
drivers/platform/x86/intel/vsec.h | 6 +
include/linux/intel_tpmi.h | 30 ++
7 files changed, 490 insertions(+), 5 deletions(-)
create mode 100644 drivers/platform/x86/intel/tpmi.c
create mode 100644 include/linux/intel_tpmi.h

--
2.31.1



2023-02-02 01:09:15

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 3/7] platform/x86/intel/vsec: Support private data

Add fields to struct intel_vsec_device, so that core module (which
creates aux bus devices) can pass private data to the client drivers.

For example there is one vsec device instance per CPU package. On a
multi package system, this private data can be used to pass the package
ID. This package id can be used by client drivers to change power
settings for a specific CPU package by targeting MMIO space of the
correct PCI device.

Signed-off-by: Srinivas Pandruvada <[email protected]>
Acked-by: David E. Box <[email protected]>
---
drivers/platform/x86/intel/vsec.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
index d02c340fd458..ae8fe92c5595 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -38,6 +38,8 @@ struct intel_vsec_device {
struct ida *ida;
struct intel_vsec_platform_info *info;
int num_resources;
+ void *priv_data;
+ size_t priv_data_size;
};

int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
--
2.31.1


2023-02-02 01:09:18

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 2/7] platform/x86/intel/vsec: Enhance and Export intel_vsec_add_aux()

Remove static for intel_vsec_add_aux() and export this interface so that
it can be used by other vsec related modules.

This driver creates aux devices by parsing PCI-VSEC, which allows
individual drivers to load on those devices. Those driver may further
create more devices on aux bus by parsing the PCI MMIO region.

For example, TPMI (Topology Aware Register and PM Capsule Interface)
creates device nodes for power management features by parsing MMIO region.

When TPMI driver creates devices, it can reuse existing function
intel_vsec_add_aux() to create aux devices with TPMI device as the parent.

Signed-off-by: Srinivas Pandruvada <[email protected]>
Acked-by: David E. Box <[email protected]>
---
drivers/platform/x86/intel/vsec.c | 16 +++++++++++-----
drivers/platform/x86/intel/vsec.h | 4 ++++
2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index a82b2a5ed99d..b936fc5776d7 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -138,8 +138,9 @@ static void intel_vsec_dev_release(struct device *dev)
kfree(intel_vsec_dev);
}

-static int intel_vsec_add_aux(struct pci_dev *pdev, struct intel_vsec_device *intel_vsec_dev,
- const char *name)
+int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
+ struct intel_vsec_device *intel_vsec_dev,
+ const char *name)
{
struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev;
int ret, id;
@@ -150,9 +151,12 @@ static int intel_vsec_add_aux(struct pci_dev *pdev, struct intel_vsec_device *in
return ret;
}

+ if (!parent)
+ parent = &pdev->dev;
+
auxdev->id = ret;
auxdev->name = name;
- auxdev->dev.parent = &pdev->dev;
+ auxdev->dev.parent = parent;
auxdev->dev.release = intel_vsec_dev_release;

ret = auxiliary_device_init(auxdev);
@@ -169,7 +173,7 @@ static int intel_vsec_add_aux(struct pci_dev *pdev, struct intel_vsec_device *in
return ret;
}

- ret = devm_add_action_or_reset(&pdev->dev, intel_vsec_remove_aux,
+ ret = devm_add_action_or_reset(parent, intel_vsec_remove_aux,
auxdev);
if (ret < 0)
return ret;
@@ -182,6 +186,7 @@ static int intel_vsec_add_aux(struct pci_dev *pdev, struct intel_vsec_device *in

return 0;
}
+EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, INTEL_VSEC);

static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header,
struct intel_vsec_platform_info *info)
@@ -239,7 +244,8 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
else
intel_vsec_dev->ida = &intel_vsec_ida;

- return intel_vsec_add_aux(pdev, intel_vsec_dev, intel_vsec_name(header->id));
+ return intel_vsec_add_aux(pdev, NULL, intel_vsec_dev,
+ intel_vsec_name(header->id));
}

static bool intel_vsec_walk_header(struct pci_dev *pdev,
diff --git a/drivers/platform/x86/intel/vsec.h b/drivers/platform/x86/intel/vsec.h
index 3deeb05cf394..d02c340fd458 100644
--- a/drivers/platform/x86/intel/vsec.h
+++ b/drivers/platform/x86/intel/vsec.h
@@ -40,6 +40,10 @@ struct intel_vsec_device {
int num_resources;
};

+int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
+ struct intel_vsec_device *intel_vsec_dev,
+ const char *name);
+
static inline struct intel_vsec_device *dev_to_ivdev(struct device *dev)
{
return container_of(dev, struct intel_vsec_device, auxdev.dev);
--
2.31.1


2023-02-02 01:09:22

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 5/7] platform/x86/intel/tpmi: Process CPU package mapping

There is one Intel Out-of-Band (OOB) PCI device per CPU package. Since
TPMI feature is exposed via OOB PCI device, there will be multiple
TPMI device instances on a multi CPU package system.

There are several PM features, which needs to associate APIC based CPU
package ID information to a TPMI instance. For example if Intel Speed
Select feature requires control of a CPU package, it needs to identify
right TPMI device instance.

There is one special TPMI ID (ID = 0x81) in the PFS. The MMIO
region of this TPMI ID points to a mapping table:
- PCI Bus ID
- PCI Device ID
- APIC based Package ID

This mapping information can be used by any PM feature driver which
requires mapping from a CPU package to a TPMI device instance.

Unlike other TPMI features, device node is not created for this feature
ID (0x81). Instead store the mapping information as platform data, which
is part of the per PCI device TPMI instance (struct intel_tpmi_info).
Later the TPMI feature drivers can get the mapping information using an
interface "tpmi_get_platform_data()"

Signed-off-by: Srinivas Pandruvada <[email protected]>
Reviewed-by: Pierre-Louis Bossart <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>
---
drivers/platform/x86/intel/tpmi.c | 72 +++++++++++++++++++++++++++++++
include/linux/intel_tpmi.h | 28 ++++++++++++
2 files changed, 100 insertions(+)
create mode 100644 include/linux/intel_tpmi.h

diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c
index 1b87b46ba8a9..e612da579b29 100644
--- a/drivers/platform/x86/intel/tpmi.c
+++ b/drivers/platform/x86/intel/tpmi.c
@@ -47,6 +47,7 @@
*/

#include <linux/auxiliary_bus.h>
+#include <linux/intel_tpmi.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -96,6 +97,7 @@ struct intel_tpmi_pm_feature {
* @vsec_dev: Pointer to intel_vsec_device structure for this TPMI device
* @feature_count: Number of TPMI of TPMI instances pointed by tpmi_features
* @pfs_start: Start of PFS offset for the TPMI instances in this device
+ * @plat_info: Stores platform info which can be used by the client drivers
*
* Stores the information for all TPMI devices enumerated from a single PCI device.
*/
@@ -104,8 +106,30 @@ struct intel_tpmi_info {
struct intel_vsec_device *vsec_dev;
int feature_count;
u64 pfs_start;
+ struct intel_tpmi_plat_info plat_info;
};

+/**
+ * struct tpmi_info_header - CPU package ID to PCI device mapping information
+ * @fn: PCI function number
+ * @dev: PCI device number
+ * @bus: PCI bus number
+ * @pkg: CPU Package id
+ * @reserved: Reserved for future use
+ * @lock: When set to 1 the register is locked and becomes read-only
+ * until next reset. Not for use by the OS driver.
+ *
+ * The structure to read hardware provided mapping information.
+ */
+struct tpmi_info_header {
+ u64 fn:3;
+ u64 dev:5;
+ u64 bus:8;
+ u64 pkg:8;
+ u64 reserved:39;
+ u64 lock:1;
+} __packed;
+
/*
* List of supported TMPI IDs.
* Some TMPI IDs are not used by Linux, so the numbers are not consecutive.
@@ -115,11 +139,20 @@ enum intel_tpmi_id {
TPMI_ID_PEM = 1, /* Power and Perf excursion Monitor */
TPMI_ID_UNCORE = 2, /* Uncore Frequency Scaling */
TPMI_ID_SST = 5, /* Speed Select Technology */
+ TPMI_INFO_ID = 0x81, /* Special ID for PCI BDF and Package ID information */
};

/* Used during auxbus device creation */
static DEFINE_IDA(intel_vsec_tpmi_ida);

+struct intel_tpmi_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev)
+{
+ struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
+
+ return vsec_dev->priv_data;
+}
+EXPORT_SYMBOL_NS_GPL(tpmi_get_platform_data, INTEL_TPMI);
+
static const char *intel_tpmi_name(enum intel_tpmi_id id)
{
switch (id) {
@@ -177,6 +210,8 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
feature_vsec_dev->pcidev = vsec_dev->pcidev;
feature_vsec_dev->resource = res;
feature_vsec_dev->num_resources = pfs->pfs_header.num_entries;
+ feature_vsec_dev->priv_data = &tpmi_info->plat_info;
+ feature_vsec_dev->priv_data_size = sizeof(tpmi_info->plat_info);
feature_vsec_dev->ida = &intel_vsec_tpmi_ida;

/*
@@ -220,6 +255,31 @@ static int tpmi_create_devices(struct intel_tpmi_info *tpmi_info)
return 0;
}

+#define TPMI_INFO_BUS_INFO_OFFSET 0x08
+
+static int tpmi_process_info(struct intel_tpmi_info *tpmi_info,
+ struct intel_tpmi_pm_feature *pfs)
+{
+ struct tpmi_info_header header;
+ void __iomem *info_mem;
+
+ info_mem = ioremap(pfs->vsec_offset + TPMI_INFO_BUS_INFO_OFFSET,
+ pfs->pfs_header.entry_size * 4 - TPMI_INFO_BUS_INFO_OFFSET);
+ if (!info_mem)
+ return -ENOMEM;
+
+ memcpy_fromio(&header, info_mem, sizeof(header));
+
+ tpmi_info->plat_info.package_id = header.pkg;
+ tpmi_info->plat_info.bus_number = header.bus;
+ tpmi_info->plat_info.device_number = header.dev;
+ tpmi_info->plat_info.function_number = header.fn;
+
+ iounmap(info_mem);
+
+ return 0;
+}
+
static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, int size)
{
void __iomem *pfs_mem;
@@ -238,6 +298,7 @@ static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, i
static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
{
struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
+ struct pci_dev *pci_dev = vsec_dev->pcidev;
struct intel_tpmi_info *tpmi_info;
u64 pfs_start = 0;
int i;
@@ -248,6 +309,7 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)

tpmi_info->vsec_dev = vsec_dev;
tpmi_info->feature_count = vsec_dev->num_resources;
+ tpmi_info->plat_info.bus_number = pci_dev->bus->number;

tpmi_info->tpmi_features = devm_kcalloc(&auxdev->dev, vsec_dev->num_resources,
sizeof(*tpmi_info->tpmi_features),
@@ -282,6 +344,16 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
pfs->pfs_header.cap_offset *= 1024;

pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset;
+
+ /*
+ * Process TPMI_INFO to get PCI device to CPU package ID.
+ * Device nodes for TPMI features are not created in this
+ * for loop. So, the mapping information will be available
+ * when actual device nodes created outside this
+ * loop via tpmi_create_devices().
+ */
+ if (pfs->pfs_header.tpmi_id == TPMI_INFO_ID)
+ tpmi_process_info(tpmi_info, pfs);
}

tpmi_info->pfs_start = pfs_start;
diff --git a/include/linux/intel_tpmi.h b/include/linux/intel_tpmi.h
new file mode 100644
index 000000000000..5b665320ecb4
--- /dev/null
+++ b/include/linux/intel_tpmi.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * intel_tpmi.h: Intel TPMI core external interface
+ */
+
+#ifndef _INTEL_TPMI_H_
+#define _INTEL_TPMI_H_
+
+/**
+ * struct intel_tpmi_plat_info - Platform information for a TPMI device instance
+ * @package_id: CPU Package id
+ * @bus_number: PCI bus number
+ * @device_number: PCI device number
+ * @function_number: PCI function number
+ *
+ * Structure to store platform data for a TPMI device instance. This
+ * struct is used to return data via tpmi_get_platform_data().
+ */
+struct intel_tpmi_plat_info {
+ u8 package_id;
+ u8 bus_number;
+ u8 device_number;
+ u8 function_number;
+};
+
+struct intel_tpmi_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev);
+
+#endif
--
2.31.1


2023-02-02 01:09:24

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 6/7] platform/x86/intel/tpmi: ADD tpmi external interface for tpmi feature drivers

Add interface to get resources and platform data. This will avoid code
duplication. These interfaces includes:
- Get resource count
- Get resource at an index

Signed-off-by: Srinivas Pandruvada <[email protected]>
Reviewed-by: Pierre-Louis Bossart <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>
---
drivers/platform/x86/intel/tpmi.c | 22 ++++++++++++++++++++++
include/linux/intel_tpmi.h | 2 ++
2 files changed, 24 insertions(+)

diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c
index e612da579b29..c60733261c89 100644
--- a/drivers/platform/x86/intel/tpmi.c
+++ b/drivers/platform/x86/intel/tpmi.c
@@ -153,6 +153,28 @@ struct intel_tpmi_plat_info *tpmi_get_platform_data(struct auxiliary_device *aux
}
EXPORT_SYMBOL_NS_GPL(tpmi_get_platform_data, INTEL_TPMI);

+int tpmi_get_resource_count(struct auxiliary_device *auxdev)
+{
+ struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
+
+ if (vsec_dev)
+ return vsec_dev->num_resources;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_count, INTEL_TPMI);
+
+struct resource *tpmi_get_resource_at_index(struct auxiliary_device *auxdev, int index)
+{
+ struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
+
+ if (vsec_dev && index < vsec_dev->num_resources)
+ return &vsec_dev->resource[index];
+
+ return NULL;
+}
+EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);
+
static const char *intel_tpmi_name(enum intel_tpmi_id id)
{
switch (id) {
diff --git a/include/linux/intel_tpmi.h b/include/linux/intel_tpmi.h
index 5b665320ecb4..f505788c05da 100644
--- a/include/linux/intel_tpmi.h
+++ b/include/linux/intel_tpmi.h
@@ -24,5 +24,7 @@ struct intel_tpmi_plat_info {
};

struct intel_tpmi_plat_info *tpmi_get_platform_data(struct auxiliary_device *auxdev);
+struct resource *tpmi_get_resource_at_index(struct auxiliary_device *auxdev, int index);
+int tpmi_get_resource_count(struct auxiliary_device *auxdev);

#endif
--
2.31.1


2023-02-02 01:09:28

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 4/7] platform/x86/intel: Intel TPMI enumeration driver

The TPMI (Topology Aware Register and PM Capsule Interface) provides a
flexible, extendable and PCIe enumerable MMIO interface for PM features.

For example Intel RAPL (Running Average Power Limit) provides a MMIO
interface using TPMI. This has advantage over traditional MSR
(Model Specific Register) interface, where a thread needs to be scheduled
on the target CPU to read or write. Also the RAPL features vary between
CPU models, and hence lot of model specific code. Here TPMI provides an
architectural interface by providing hierarchical tables and fields,
which will not need any model specific implementation.

The TPMI interface uses a PCI VSEC structure to expose the location of
MMIO region.

This VSEC structure is present in the PCI configuration space of the
Intel Out-of-Band (OOB) device, which is handled by the Intel VSEC
driver. The Intel VSEC driver parses VSEC structures present in the PCI
configuration space of the given device and creates an auxiliary device
object for each of them. In particular, it creates an auxiliary device
object representing TPMI that can be bound by an auxiliary driver.

Introduce a TPMI driver that will bind to the TPMI auxiliary device
object created by the Intel VSEC driver.

The TPMI specification defines a PFS (PM Feature Structure) table.
This table is present in the TPMI MMIO region. The starting address
of PFS is derived from the tBIR (Bar Indicator Register) and "Address"
field from the VSEC header.

Each TPMI PM feature has one entry in the PFS with a unique TPMI
ID and its access details. The TPMI driver creates device nodes
for the supported PM features.

The names of the devices created by the TPMI driver start with the
"intel_vsec.tpmi-" prefix which is followed by a specific name of the
given PM feature (for example, "intel_vsec.tpmi-rapl.0").

The device nodes are create by using interface "intel_vsec_add_aux()"
provided by the Intel VSEC driver.

Signed-off-by: Srinivas Pandruvada <[email protected]>
Reviewed-by: Pierre-Louis Bossart <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>
---
drivers/platform/x86/intel/Kconfig | 13 ++
drivers/platform/x86/intel/Makefile | 4 +
drivers/platform/x86/intel/tpmi.c | 321 ++++++++++++++++++++++++++++
3 files changed, 338 insertions(+)
create mode 100644 drivers/platform/x86/intel/tpmi.c

diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig
index d5a33473e838..bbbd9e54e9ee 100644
--- a/drivers/platform/x86/intel/Kconfig
+++ b/drivers/platform/x86/intel/Kconfig
@@ -182,6 +182,19 @@ config INTEL_SMARTCONNECT
This driver checks to determine whether the device has Intel Smart
Connect enabled, and if so disables it.

+config INTEL_TPMI
+ tristate "Intel Topology Aware Register and PM Capsule Interface (TPMI)"
+ depends on INTEL_VSEC
+ depends on X86_64
+ help
+ The Intel Topology Aware Register and PM Capsule Interface (TPMI),
+ provides enumerable MMIO interface for power management features.
+ This driver creates devices, so that other PM feature driver can
+ be loaded for PM specific feature operation.
+
+ To compile this driver as a module, choose M here: the module will
+ be called intel_vsec_tpmi.
+
config INTEL_TURBO_MAX_3
bool "Intel Turbo Boost Max Technology 3.0 enumeration driver"
depends on X86_64 && SCHED_MC_PRIO
diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile
index 717933dd0cfd..411df4040427 100644
--- a/drivers/platform/x86/intel/Makefile
+++ b/drivers/platform/x86/intel/Makefile
@@ -47,6 +47,10 @@ obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
intel_punit_ipc-y := punit_ipc.o
obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o

+# TPMI drivers
+intel_vsec_tpmi-y := tpmi.o
+obj-$(CONFIG_INTEL_TPMI) += intel_vsec_tpmi.o
+
# Intel Uncore drivers
intel-rst-y := rst.o
obj-$(CONFIG_INTEL_RST) += intel-rst.o
diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c
new file mode 100644
index 000000000000..1b87b46ba8a9
--- /dev/null
+++ b/drivers/platform/x86/intel/tpmi.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * intel-tpmi : Driver to enumerate TPMI features and create devices
+ *
+ * Copyright (c) 2023, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * The TPMI (Topology Aware Register and PM Capsule Interface) provides a
+ * flexible, extendable and PCIe enumerable MMIO interface for PM features.
+ *
+ * For example Intel RAPL (Running Average Power Limit) provides a MMIO
+ * interface using TPMI. This has advantage over traditional MSR
+ * (Model Specific Register) interface, where a thread needs to be scheduled
+ * on the target CPU to read or write. Also the RAPL features vary between
+ * CPU models, and hence lot of model specific code. Here TPMI provides an
+ * architectural interface by providing hierarchical tables and fields,
+ * which will not need any model specific implementation.
+ *
+ * The TPMI interface uses a PCI VSEC structure to expose the location of
+ * MMIO region.
+ *
+ * This VSEC structure is present in the PCI configuration space of the
+ * Intel Out-of-Band (OOB) device, which is handled by the Intel VSEC
+ * driver. The Intel VSEC driver parses VSEC structures present in the PCI
+ * configuration space of the given device and creates an auxiliary device
+ * object for each of them. In particular, it creates an auxiliary device
+ * object representing TPMI that can be bound by an auxiliary driver.
+ *
+ * This TPMI driver will bind to the TPMI auxiliary device object created
+ * by the Intel VSEC driver.
+ *
+ * The TPMI specification defines a PFS (PM Feature Structure) table.
+ * This table is present in the TPMI MMIO region. The starting address
+ * of PFS is derived from the tBIR (Bar Indicator Register) and "Address"
+ * field from the VSEC header.
+ *
+ * Each TPMI PM feature has one entry in the PFS with a unique TPMI
+ * ID and its access details. The TPMI driver creates device nodes
+ * for the supported PM features.
+ *
+ * The names of the devices created by the TPMI driver start with the
+ * "intel_vsec.tpmi-" prefix which is followed by a specific name of the
+ * given PM feature (for example, "intel_vsec.tpmi-rapl.0").
+ *
+ * The device nodes are create by using interface "intel_vsec_add_aux()"
+ * provided by the Intel VSEC driver.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "vsec.h"
+
+/**
+ * struct intel_tpmi_pfs_entry - TPMI PM Feature Structure (PFS) entry
+ * @tpmi_id: TPMI feature identifier (what the feature is and its data format).
+ * @num_entries: Number of feature interface instances present in the PFS.
+ * This represents the maximum number of Power domains in the SoC.
+ * @entry_size: Interface instance entry size in 32-bit words.
+ * @cap_offset: Offset from the PM_Features base address to the base of the PM VSEC
+ * register bank in KB.
+ * @attribute: Feature attribute: 0=BIOS. 1=OS. 2-3=Reserved.
+ * @reserved: Bits for use in the future.
+ *
+ * Represents one TPMI feature entry data in the PFS retrieved as is
+ * from the hardware.
+ */
+struct intel_tpmi_pfs_entry {
+ u64 tpmi_id:8;
+ u64 num_entries:8;
+ u64 entry_size:16;
+ u64 cap_offset:16;
+ u64 attribute:2;
+ u64 reserved:14;
+} __packed;
+
+/**
+ * struct intel_tpmi_pm_feature - TPMI PM Feature information for a TPMI ID
+ * @pfs_header: PFS header retireved from the hardware.
+ * @vsec_offset: Starting MMIO address for this feature in bytes. Essentially
+ * this offset = "Address" from VSEC header + PFS Capability
+ * offset for this feature entry.
+ *
+ * Represents TPMI instance information for one TPMI ID.
+ */
+struct intel_tpmi_pm_feature {
+ struct intel_tpmi_pfs_entry pfs_header;
+ unsigned int vsec_offset;
+};
+
+/**
+ * struct intel_tpmi_info - TPMI information for all IDs in an instance
+ * @tpmi_features: Pointer to a list of TPMI feature instances
+ * @vsec_dev: Pointer to intel_vsec_device structure for this TPMI device
+ * @feature_count: Number of TPMI of TPMI instances pointed by tpmi_features
+ * @pfs_start: Start of PFS offset for the TPMI instances in this device
+ *
+ * Stores the information for all TPMI devices enumerated from a single PCI device.
+ */
+struct intel_tpmi_info {
+ struct intel_tpmi_pm_feature *tpmi_features;
+ struct intel_vsec_device *vsec_dev;
+ int feature_count;
+ u64 pfs_start;
+};
+
+/*
+ * List of supported TMPI IDs.
+ * Some TMPI IDs are not used by Linux, so the numbers are not consecutive.
+ */
+enum intel_tpmi_id {
+ TPMI_ID_RAPL = 0, /* Running Average Power Limit */
+ TPMI_ID_PEM = 1, /* Power and Perf excursion Monitor */
+ TPMI_ID_UNCORE = 2, /* Uncore Frequency Scaling */
+ TPMI_ID_SST = 5, /* Speed Select Technology */
+};
+
+/* Used during auxbus device creation */
+static DEFINE_IDA(intel_vsec_tpmi_ida);
+
+static const char *intel_tpmi_name(enum intel_tpmi_id id)
+{
+ switch (id) {
+ case TPMI_ID_RAPL:
+ return "rapl";
+ case TPMI_ID_PEM:
+ return "pem";
+ case TPMI_ID_UNCORE:
+ return "uncore";
+ case TPMI_ID_SST:
+ return "sst";
+ default:
+ return NULL;
+ }
+}
+
+/* String Length for tpmi-"feature_name(upto 8 bytes)" */
+#define TPMI_FEATURE_NAME_LEN 14
+
+static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
+ struct intel_tpmi_pm_feature *pfs,
+ u64 pfs_start)
+{
+ struct intel_vsec_device *vsec_dev = tpmi_info->vsec_dev;
+ char feature_id_name[TPMI_FEATURE_NAME_LEN];
+ struct intel_vsec_device *feature_vsec_dev;
+ struct resource *res, *tmp;
+ const char *name;
+ int ret, i;
+
+ name = intel_tpmi_name(pfs->pfs_header.tpmi_id);
+ if (!name)
+ return -EOPNOTSUPP;
+
+ feature_vsec_dev = kzalloc(sizeof(*feature_vsec_dev), GFP_KERNEL);
+ if (!feature_vsec_dev)
+ return -ENOMEM;
+
+ res = kcalloc(pfs->pfs_header.num_entries, sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ ret = -ENOMEM;
+ goto free_vsec;
+ }
+
+ snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name);
+
+ for (i = 0, tmp = res; i < pfs->pfs_header.num_entries; i++, tmp++) {
+ u64 entry_size_bytes = pfs->pfs_header.entry_size * 4;
+
+ tmp->start = pfs->vsec_offset + entry_size_bytes * i;
+ tmp->end = tmp->start + entry_size_bytes - 1;
+ tmp->flags = IORESOURCE_MEM;
+ }
+
+ feature_vsec_dev->pcidev = vsec_dev->pcidev;
+ feature_vsec_dev->resource = res;
+ feature_vsec_dev->num_resources = pfs->pfs_header.num_entries;
+ feature_vsec_dev->ida = &intel_vsec_tpmi_ida;
+
+ /*
+ * intel_vsec_add_aux() is resource managed, no explicit
+ * delete is required on error or on module unload.
+ */
+ ret = intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev,
+ feature_vsec_dev, feature_id_name);
+ if (ret)
+ goto free_res;
+
+ return 0;
+
+free_res:
+ kfree(res);
+free_vsec:
+ kfree(feature_vsec_dev);
+
+ return ret;
+}
+
+static int tpmi_create_devices(struct intel_tpmi_info *tpmi_info)
+{
+ struct intel_vsec_device *vsec_dev = tpmi_info->vsec_dev;
+ int ret, i;
+
+ for (i = 0; i < vsec_dev->num_resources; i++) {
+ ret = tpmi_create_device(tpmi_info, &tpmi_info->tpmi_features[i],
+ tpmi_info->pfs_start);
+ /*
+ * Fail, if the supported features fails to create device,
+ * otherwise, continue. Even if one device failed to create,
+ * fail the loading of driver. Since intel_vsec_add_aux()
+ * is resource managed, no clean up is required for the
+ * successfully created devices.
+ */
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tpmi_fetch_pfs_header(struct intel_tpmi_pm_feature *pfs, u64 start, int size)
+{
+ void __iomem *pfs_mem;
+
+ pfs_mem = ioremap(start, size);
+ if (!pfs_mem)
+ return -ENOMEM;
+
+ memcpy_fromio(&pfs->pfs_header, pfs_mem, sizeof(pfs->pfs_header));
+
+ iounmap(pfs_mem);
+
+ return 0;
+}
+
+static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
+{
+ struct intel_vsec_device *vsec_dev = auxdev_to_ivdev(auxdev);
+ struct intel_tpmi_info *tpmi_info;
+ u64 pfs_start = 0;
+ int i;
+
+ tpmi_info = devm_kzalloc(&auxdev->dev, sizeof(*tpmi_info), GFP_KERNEL);
+ if (!tpmi_info)
+ return -ENOMEM;
+
+ tpmi_info->vsec_dev = vsec_dev;
+ tpmi_info->feature_count = vsec_dev->num_resources;
+
+ tpmi_info->tpmi_features = devm_kcalloc(&auxdev->dev, vsec_dev->num_resources,
+ sizeof(*tpmi_info->tpmi_features),
+ GFP_KERNEL);
+ if (!tpmi_info->tpmi_features)
+ return -ENOMEM;
+
+ for (i = 0; i < vsec_dev->num_resources; i++) {
+ struct intel_tpmi_pm_feature *pfs;
+ struct resource *res;
+ u64 res_start;
+ int size, ret;
+
+ pfs = &tpmi_info->tpmi_features[i];
+
+ res = &vsec_dev->resource[i];
+ if (!res)
+ continue;
+
+ res_start = res->start;
+ size = resource_size(res);
+ if (size < 0)
+ continue;
+
+ ret = tpmi_fetch_pfs_header(pfs, res_start, size);
+ if (ret)
+ continue;
+
+ if (!pfs_start)
+ pfs_start = res_start;
+
+ pfs->pfs_header.cap_offset *= 1024;
+
+ pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset;
+ }
+
+ tpmi_info->pfs_start = pfs_start;
+
+ auxiliary_set_drvdata(auxdev, tpmi_info);
+
+ return tpmi_create_devices(tpmi_info);
+}
+
+static int tpmi_probe(struct auxiliary_device *auxdev,
+ const struct auxiliary_device_id *id)
+{
+ return intel_vsec_tpmi_init(auxdev);
+}
+
+/*
+ * Remove callback is not needed currently as there is no
+ * cleanup required. All memory allocs are device managed. All
+ * devices created by this modules are also device managed.
+ */
+
+static const struct auxiliary_device_id tpmi_id_table[] = {
+ { .name = "intel_vsec.tpmi" },
+ {}
+};
+MODULE_DEVICE_TABLE(auxiliary, tpmi_id_table);
+
+static struct auxiliary_driver tpmi_aux_driver = {
+ .id_table = tpmi_id_table,
+ .probe = tpmi_probe,
+};
+
+module_auxiliary_driver(tpmi_aux_driver);
+
+MODULE_IMPORT_NS(INTEL_VSEC);
+MODULE_DESCRIPTION("Intel TPMI enumeration module");
+MODULE_LICENSE("GPL");
--
2.31.1


2023-02-02 01:09:30

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 7/7] MAINTAINERS: Add entry for TPMI driver

Add entry for TPMI (Topology Aware Register and PM Capsule Interface)
driver.

Signed-off-by: Srinivas Pandruvada <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f61eb221415b..6f3aaa7161d6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10683,6 +10683,12 @@ S: Maintained
F: arch/x86/include/asm/intel_telemetry.h
F: drivers/platform/x86/intel/telemetry/

+INTEL TPMI DRIVER
+M: Srinivas Pandruvada <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/platform/x86/intel/tpmi.c
+
INTEL UNCORE FREQUENCY CONTROL
M: Srinivas Pandruvada <[email protected]>
L: [email protected]
--
2.31.1


2023-02-06 12:50:22

by Hans de Goede

[permalink] [raw]
Subject: Re: [PATCH 0/7] Add TPMI support

Hi,

On 2/2/23 02:07, Srinivas Pandruvada wrote:
> The TPMI (Topology Aware Register and PM Capsule Interface) provides a
> flexible, extendable and PCIe enumerable MMIO interface for PM features.
>
> For example Intel Speed Select Technology (Intel SST) can replace all
> mailbox commands with direct MMIO access. This reduces latency for
> SST commands and also defines an architectural interface which will
> persist for several next generations.
>
> Also Intel RAPL (Running Average Power Limit) provides a MMIO
> interface using TPMI. This has advantage over traditional MSR
> (Model Specific Register) interface, where a thread needs to be scheduled
> on the target CPU to read or write. Also the RAPL features vary between
> CPU models, and hence lot of model specific code. Here TPMI provides an
> architectural interface by providing hierarchical tables and fields,
> which will not need any model specific implementation.
>
> Same value is for Intel Uncore frequency where MSR interface can't
> be used because of multiple domains.
>
> The TPMI interface uses a PCI VSEC structure to expose the location of
> MMIO region, which is handled by Intel VSEC driver. Intel VSEC driver is
> already present in upstream kernel.
>
> This series contains the base driver, which parses TPMI MMIO region
> and creates device nodes for supported features. The current set of
> PM feature support includes, Intel Speed Select, RAPL, Uncore frequency
> scaling.
>
> The first there patches updates Intel VSEC driver to add TPMI VSEC ID
> and enhance to reuse the code.
> The next three patches adds TPMI base driver support.
> The last patch adds MAINTAINERS entry.
>
> The TPMI documentation can be downloaded from:
> https://github.com/intel/tpmi_power_management
>
> This series cleanly applies on 6.2-rc1.

Thank you for your patch-series, I've applied the series to my
review-hans branch:
https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans

Note it will show up in my review-hans branch once I've pushed my
local branch there, which might take a while.

Once I've run some tests on this branch the patches there will be
added to the platform-drivers-x86/for-next branch and eventually
will be included in the pdx86 pull-request to Linus for the next
merge-window.

Regards,

Hans




> Srinivas Pandruvada (7):
> platform/x86/intel/vsec: Add TPMI ID
> platform/x86/intel/vsec: Enhance and Export intel_vsec_add_aux()
> platform/x86/intel/vsec: Support private data
> platform/x86/intel: Intel TPMI enumeration driver
> platform/x86/intel/tpmi: Process CPU package mapping
> platform/x86/intel/tpmi: ADD tpmi external interface for tpmi feature
> drivers
> MAINTAINERS: Add entry for TPMI driver
>
> MAINTAINERS | 6 +
> drivers/platform/x86/intel/Kconfig | 13 +
> drivers/platform/x86/intel/Makefile | 4 +
> drivers/platform/x86/intel/tpmi.c | 415 ++++++++++++++++++++++++++++
> drivers/platform/x86/intel/vsec.c | 21 +-
> drivers/platform/x86/intel/vsec.h | 6 +
> include/linux/intel_tpmi.h | 30 ++
> 7 files changed, 490 insertions(+), 5 deletions(-)
> create mode 100644 drivers/platform/x86/intel/tpmi.c
> create mode 100644 include/linux/intel_tpmi.h
>


2023-02-06 12:51:06

by Hans de Goede

[permalink] [raw]
Subject: Re: [PATCH 7/7] MAINTAINERS: Add entry for TPMI driver

Hi,

On 2/2/23 02:07, Srinivas Pandruvada wrote:
> Add entry for TPMI (Topology Aware Register and PM Capsule Interface)
> driver.
>
> Signed-off-by: Srinivas Pandruvada <[email protected]>
> ---
> MAINTAINERS | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f61eb221415b..6f3aaa7161d6 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10683,6 +10683,12 @@ S: Maintained
> F: arch/x86/include/asm/intel_telemetry.h
> F: drivers/platform/x86/intel/telemetry/
>
> +INTEL TPMI DRIVER
> +M: Srinivas Pandruvada <[email protected]>
> +L: [email protected]
> +S: Maintained
> +F: drivers/platform/x86/intel/tpmi.c

Note this is missing:

F: include/linux/intel_tpmi.h

I have fixed this up while merging this.

Regards,

Hans





> +
> INTEL UNCORE FREQUENCY CONTROL
> M: Srinivas Pandruvada <[email protected]>
> L: [email protected]


2023-02-06 12:55:55

by Hans de Goede

[permalink] [raw]
Subject: Re: [PATCH 0/7] Add TPMI support

Hi,

On 2/6/23 13:49, Hans de Goede wrote:

> Thank you for your patch-series, I've applied the series to my
> review-hans branch:
> https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans
>
> Note it will show up in my review-hans branch once I've pushed my
> local branch there, which might take a while.
>
> Once I've run some tests on this branch the patches there will be
> added to the platform-drivers-x86/for-next branch and eventually
> will be included in the pdx86 pull-request to Linus for the next
> merge-window.

One thing which I did notice, which is a pre-existing problem
is that the IDA accesses in drivers/platform/x86/intel/vsec.c
are not protected by any locking.

This is likely ok for now because there is only 1 PCI device
per type of ida and the enumeration of the vsec devices
under the PCI device is done in a single loop, so all
IDA accesses are single threaded atm.

But still IMHO it would be good to protect the IDA accesses
(ida_alloc() / ida_free()) with a mutex to protect against
any future races.

I think that a single global static mutex inside
drivers/platform/x86/intel/vsec.c to protect the
ida calls there should suffice for this.

Regards,

Hans




2023-02-06 13:30:11

by srinivas pandruvada

[permalink] [raw]
Subject: Re: [PATCH 0/7] Add TPMI support

Hi Hans,

On Mon, 2023-02-06 at 13:55 +0100, Hans de Goede wrote:
> Hi,
>
> On 2/6/23 13:49, Hans de Goede wrote:
>
> > Thank you for your patch-series, I've applied the series to my
> > review-hans branch:
> > https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans
> >
> > Note it will show up in my review-hans branch once I've pushed my
> > local branch there, which might take a while.
> >
> > Once I've run some tests on this branch the patches there will be
> > added to the platform-drivers-x86/for-next branch and eventually
> > will be included in the pdx86 pull-request to Linus for the next
> > merge-window.
>
> One thing which I did notice, which is a pre-existing problem
> is that the IDA accesses in drivers/platform/x86/intel/vsec.c
> are not protected by any locking.
>
> This is likely ok for now because there is only 1 PCI device
> per type of ida and the enumeration of the vsec devices
> under the PCI device is done in a single loop, so all
> IDA accesses are single threaded atm.
>
> But still IMHO it would be good to protect the IDA accesses
> (ida_alloc() / ida_free()) with a mutex to protect against
> any future races.
>
> I think that a single global static mutex inside
> drivers/platform/x86/intel/vsec.c to protect the
> ida calls there should suffice for this.
Let me look into this and get back.

Thanks,
Srinivas

>
> Regards,
>
> Hans
>
>
>


2023-02-10 08:04:36

by srinivas pandruvada

[permalink] [raw]
Subject: Re: [PATCH 0/7] Add TPMI support

Hi Hans,

On Mon, 2023-02-06 at 13:49 +0100, Hans de Goede wrote:
> Hi,
>
> On 2/2/23 02:07, Srinivas Pandruvada wrote:
>
>
[...]

> Thank you for your patch-series, I've applied the series to my
> review-hans branch:
> https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans
>
>
Thanks for the help here.

> Note it will show up in my review-hans branch once I've pushed my
> local branch there, which might take a while.
>
> Once I've run some tests on this branch the patches there will be
> added to the platform-drivers-x86/for-next branch and eventually
> will be included in the pdx86 pull-request to Linus for the next
> merge-window.
I guess this will appear in 6.3 merge window.

Can I post next set of patches (targeted for 6.4)?

Thanks,
Srinivas

>
> Regards,
>
> Hans
>
>
>
>
> > Srinivas Pandruvada (7):
> >   platform/x86/intel/vsec: Add TPMI ID
> >   platform/x86/intel/vsec: Enhance and Export intel_vsec_add_aux()
> >   platform/x86/intel/vsec: Support private data
> >   platform/x86/intel: Intel TPMI enumeration driver
> >   platform/x86/intel/tpmi: Process CPU package mapping
> >   platform/x86/intel/tpmi: ADD tpmi external interface for tpmi
> > feature
> >     drivers
> >   MAINTAINERS: Add entry for TPMI driver
> >
> >  MAINTAINERS                         |   6 +
> >  drivers/platform/x86/intel/Kconfig  |  13 +
> >  drivers/platform/x86/intel/Makefile |   4 +
> >  drivers/platform/x86/intel/tpmi.c   | 415
> > ++++++++++++++++++++++++++++
> >  drivers/platform/x86/intel/vsec.c   |  21 +-
> >  drivers/platform/x86/intel/vsec.h   |   6 +
> >  include/linux/intel_tpmi.h          |  30 ++
> >  7 files changed, 490 insertions(+), 5 deletions(-)
> >  create mode 100644 drivers/platform/x86/intel/tpmi.c
> >  create mode 100644 include/linux/intel_tpmi.h
> >
>


2023-02-10 14:25:50

by Hans de Goede

[permalink] [raw]
Subject: Re: [PATCH 0/7] Add TPMI support

Hi,

On 2/10/23 09:04, srinivas pandruvada wrote:
> Hi Hans,
>
> On Mon, 2023-02-06 at 13:49 +0100, Hans de Goede wrote:
>> Hi,
>>
>> On 2/2/23 02:07, Srinivas Pandruvada wrote:
>>
>>
> [...]
>
>> Thank you for your patch-series, I've applied the series to my
>> review-hans branch:
>> https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans
>>
>>
> Thanks for the help here.

You're welcome.

>> Note it will show up in my review-hans branch once I've pushed my
>> local branch there, which might take a while.
>>
>> Once I've run some tests on this branch the patches there will be
>> added to the platform-drivers-x86/for-next branch and eventually
>> will be included in the pdx86 pull-request to Linus for the next
>> merge-window.
> I guess this will appear in 6.3 merge window.

Yes I plan to push my review-hans branch to for-next shortly.

> Can I post next set of patches (targeted for 6.4)?

Yes please, I'm not sure if I can review them next week,
but that will also give other people a chance to take
a look and comment so getting them out there would be good.

Regards,

Hans




>>> Srinivas Pandruvada (7):
>>>   platform/x86/intel/vsec: Add TPMI ID
>>>   platform/x86/intel/vsec: Enhance and Export intel_vsec_add_aux()
>>>   platform/x86/intel/vsec: Support private data
>>>   platform/x86/intel: Intel TPMI enumeration driver
>>>   platform/x86/intel/tpmi: Process CPU package mapping
>>>   platform/x86/intel/tpmi: ADD tpmi external interface for tpmi
>>> feature
>>>     drivers
>>>   MAINTAINERS: Add entry for TPMI driver
>>>
>>>  MAINTAINERS                         |   6 +
>>>  drivers/platform/x86/intel/Kconfig  |  13 +
>>>  drivers/platform/x86/intel/Makefile |   4 +
>>>  drivers/platform/x86/intel/tpmi.c   | 415
>>> ++++++++++++++++++++++++++++
>>>  drivers/platform/x86/intel/vsec.c   |  21 +-
>>>  drivers/platform/x86/intel/vsec.h   |   6 +
>>>  include/linux/intel_tpmi.h          |  30 ++
>>>  7 files changed, 490 insertions(+), 5 deletions(-)
>>>  create mode 100644 drivers/platform/x86/intel/tpmi.c
>>>  create mode 100644 include/linux/intel_tpmi.h
>>>
>>
>