-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'ib-mfd-x86-v5.11' into review-hans
Immutable branch between MFD and x86 due for the v5.11 merge window
- Loading branch information
Showing
12 changed files
with
1,238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
What: /sys/class/intel_pmt/ | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: David Box <david.e.box@linux.intel.com> | ||
Description: | ||
The intel_pmt/ class directory contains information for | ||
devices that expose hardware telemetry using Intel Platform | ||
Monitoring Technology (PMT) | ||
|
||
What: /sys/class/intel_pmt/telem<x> | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: David Box <david.e.box@linux.intel.com> | ||
Description: | ||
The telem<x> directory contains files describing an instance of | ||
a PMT telemetry device that exposes hardware telemetry. Each | ||
telem<x> directory has an associated telem file. This file | ||
may be opened and mapped or read to access the telemetry space | ||
of the device. The register layout of the telemetry space is | ||
determined from an XML file that matches the PCI device id and | ||
GUID for the device. | ||
|
||
What: /sys/class/intel_pmt/telem<x>/telem | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: David Box <david.e.box@linux.intel.com> | ||
Description: | ||
(RO) The telemetry data for this telemetry device. This file | ||
may be mapped or read to obtain the data. | ||
|
||
What: /sys/class/intel_pmt/telem<x>/guid | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: David Box <david.e.box@linux.intel.com> | ||
Description: | ||
(RO) The GUID for this telemetry device. The GUID identifies | ||
the version of the XML file for the parent device that is to | ||
be used to get the register layout. | ||
|
||
What: /sys/class/intel_pmt/telem<x>/size | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: David Box <david.e.box@linux.intel.com> | ||
Description: | ||
(RO) The size of telemetry region in bytes that corresponds to | ||
the mapping size for the telem file. | ||
|
||
What: /sys/class/intel_pmt/telem<x>/offset | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: David Box <david.e.box@linux.intel.com> | ||
Description: | ||
(RO) The offset of telemetry region in bytes that corresponds to | ||
the mapping for the telem file. | ||
|
||
What: /sys/class/intel_pmt/crashlog<x> | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: Alexander Duyck <alexander.h.duyck@linux.intel.com> | ||
Description: | ||
The crashlog<x> directory contains files for configuring an | ||
instance of a PMT crashlog device that can perform crash data | ||
recording. Each crashlog<x> device has an associated crashlog | ||
file. This file can be opened and mapped or read to access the | ||
resulting crashlog buffer. The register layout for the buffer | ||
can be determined from an XML file of specified GUID for the | ||
parent device. | ||
|
||
What: /sys/class/intel_pmt/crashlog<x>/crashlog | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: David Box <david.e.box@linux.intel.com> | ||
Description: | ||
(RO) The crashlog buffer for this crashlog device. This file | ||
may be mapped or read to obtain the data. | ||
|
||
What: /sys/class/intel_pmt/crashlog<x>/guid | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: Alexander Duyck <alexander.h.duyck@linux.intel.com> | ||
Description: | ||
(RO) The GUID for this crashlog device. The GUID identifies the | ||
version of the XML file for the parent device that should be | ||
used to determine the register layout. | ||
|
||
What: /sys/class/intel_pmt/crashlog<x>/size | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: Alexander Duyck <alexander.h.duyck@linux.intel.com> | ||
Description: | ||
(RO) The length of the result buffer in bytes that corresponds | ||
to the size for the crashlog buffer. | ||
|
||
What: /sys/class/intel_pmt/crashlog<x>/offset | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: Alexander Duyck <alexander.h.duyck@linux.intel.com> | ||
Description: | ||
(RO) The offset of the buffer in bytes that corresponds | ||
to the mapping for the crashlog device. | ||
|
||
What: /sys/class/intel_pmt/crashlog<x>/enable | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: Alexander Duyck <alexander.h.duyck@linux.intel.com> | ||
Description: | ||
(RW) Boolean value controlling if the crashlog functionality | ||
is enabled for the crashlog device. | ||
|
||
What: /sys/class/intel_pmt/crashlog<x>/trigger | ||
Date: October 2020 | ||
KernelVersion: 5.10 | ||
Contact: Alexander Duyck <alexander.h.duyck@linux.intel.com> | ||
Description: | ||
(RW) Boolean value controlling the triggering of the crashlog | ||
device node. When read it provides data on if the crashlog has | ||
been triggered. When written to it can be used to either clear | ||
the current trigger by writing false, or to trigger a new | ||
event if the trigger is not currently set. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Intel Platform Monitoring Technology PMT driver | ||
* | ||
* Copyright (c) 2020, Intel Corporation. | ||
* All Rights Reserved. | ||
* | ||
* Author: David E. Box <david.e.box@linux.intel.com> | ||
*/ | ||
|
||
#include <linux/bits.h> | ||
#include <linux/kernel.h> | ||
#include <linux/mfd/core.h> | ||
#include <linux/module.h> | ||
#include <linux/pci.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/pm.h> | ||
#include <linux/pm_runtime.h> | ||
#include <linux/types.h> | ||
|
||
/* Intel DVSEC capability vendor space offsets */ | ||
#define INTEL_DVSEC_ENTRIES 0xA | ||
#define INTEL_DVSEC_SIZE 0xB | ||
#define INTEL_DVSEC_TABLE 0xC | ||
#define INTEL_DVSEC_TABLE_BAR(x) ((x) & GENMASK(2, 0)) | ||
#define INTEL_DVSEC_TABLE_OFFSET(x) ((x) & GENMASK(31, 3)) | ||
#define INTEL_DVSEC_ENTRY_SIZE 4 | ||
|
||
/* PMT capabilities */ | ||
#define DVSEC_INTEL_ID_TELEMETRY 2 | ||
#define DVSEC_INTEL_ID_WATCHER 3 | ||
#define DVSEC_INTEL_ID_CRASHLOG 4 | ||
|
||
struct intel_dvsec_header { | ||
u16 length; | ||
u16 id; | ||
u8 num_entries; | ||
u8 entry_size; | ||
u8 tbir; | ||
u32 offset; | ||
}; | ||
|
||
enum pmt_quirks { | ||
/* Watcher capability not supported */ | ||
PMT_QUIRK_NO_WATCHER = BIT(0), | ||
|
||
/* Crashlog capability not supported */ | ||
PMT_QUIRK_NO_CRASHLOG = BIT(1), | ||
|
||
/* Use shift instead of mask to read discovery table offset */ | ||
PMT_QUIRK_TABLE_SHIFT = BIT(2), | ||
}; | ||
|
||
struct pmt_platform_info { | ||
unsigned long quirks; | ||
}; | ||
|
||
static const struct pmt_platform_info tgl_info = { | ||
.quirks = PMT_QUIRK_NO_WATCHER | PMT_QUIRK_NO_CRASHLOG | | ||
PMT_QUIRK_TABLE_SHIFT, | ||
}; | ||
|
||
static int pmt_add_dev(struct pci_dev *pdev, struct intel_dvsec_header *header, | ||
unsigned long quirks) | ||
{ | ||
struct device *dev = &pdev->dev; | ||
struct resource *res, *tmp; | ||
struct mfd_cell *cell; | ||
const char *name; | ||
int count = header->num_entries; | ||
int size = header->entry_size; | ||
int id = header->id; | ||
int i; | ||
|
||
switch (id) { | ||
case DVSEC_INTEL_ID_TELEMETRY: | ||
name = "pmt_telemetry"; | ||
break; | ||
case DVSEC_INTEL_ID_WATCHER: | ||
if (quirks & PMT_QUIRK_NO_WATCHER) { | ||
dev_info(dev, "Watcher not supported\n"); | ||
return 0; | ||
} | ||
name = "pmt_watcher"; | ||
break; | ||
case DVSEC_INTEL_ID_CRASHLOG: | ||
if (quirks & PMT_QUIRK_NO_CRASHLOG) { | ||
dev_info(dev, "Crashlog not supported\n"); | ||
return 0; | ||
} | ||
name = "pmt_crashlog"; | ||
break; | ||
default: | ||
dev_err(dev, "Unrecognized PMT capability: %d\n", id); | ||
return -EINVAL; | ||
} | ||
|
||
if (!header->num_entries || !header->entry_size) { | ||
dev_err(dev, "Invalid count or size for %s header\n", name); | ||
return -EINVAL; | ||
} | ||
|
||
cell = devm_kzalloc(dev, sizeof(*cell), GFP_KERNEL); | ||
if (!cell) | ||
return -ENOMEM; | ||
|
||
res = devm_kcalloc(dev, count, sizeof(*res), GFP_KERNEL); | ||
if (!res) | ||
return -ENOMEM; | ||
|
||
if (quirks & PMT_QUIRK_TABLE_SHIFT) | ||
header->offset >>= 3; | ||
|
||
/* | ||
* The PMT DVSEC contains the starting offset and count for a block of | ||
* discovery tables, each providing access to monitoring facilities for | ||
* a section of the device. Create a resource list of these tables to | ||
* provide to the driver. | ||
*/ | ||
for (i = 0, tmp = res; i < count; i++, tmp++) { | ||
tmp->start = pdev->resource[header->tbir].start + | ||
header->offset + i * (size << 2); | ||
tmp->end = tmp->start + (size << 2) - 1; | ||
tmp->flags = IORESOURCE_MEM; | ||
} | ||
|
||
cell->resources = res; | ||
cell->num_resources = count; | ||
cell->name = name; | ||
|
||
return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, | ||
NULL); | ||
} | ||
|
||
static int pmt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
{ | ||
struct pmt_platform_info *info; | ||
unsigned long quirks = 0; | ||
bool found_devices = false; | ||
int ret, pos = 0; | ||
|
||
ret = pcim_enable_device(pdev); | ||
if (ret) | ||
return ret; | ||
|
||
info = (struct pmt_platform_info *)id->driver_data; | ||
|
||
if (info) | ||
quirks = info->quirks; | ||
|
||
do { | ||
struct intel_dvsec_header header; | ||
u32 table; | ||
u16 vid; | ||
|
||
pos = pci_find_next_ext_capability(pdev, pos, PCI_EXT_CAP_ID_DVSEC); | ||
if (!pos) | ||
break; | ||
|
||
pci_read_config_word(pdev, pos + PCI_DVSEC_HEADER1, &vid); | ||
if (vid != PCI_VENDOR_ID_INTEL) | ||
continue; | ||
|
||
pci_read_config_word(pdev, pos + PCI_DVSEC_HEADER2, | ||
&header.id); | ||
pci_read_config_byte(pdev, pos + INTEL_DVSEC_ENTRIES, | ||
&header.num_entries); | ||
pci_read_config_byte(pdev, pos + INTEL_DVSEC_SIZE, | ||
&header.entry_size); | ||
pci_read_config_dword(pdev, pos + INTEL_DVSEC_TABLE, | ||
&table); | ||
|
||
header.tbir = INTEL_DVSEC_TABLE_BAR(table); | ||
header.offset = INTEL_DVSEC_TABLE_OFFSET(table); | ||
|
||
ret = pmt_add_dev(pdev, &header, quirks); | ||
if (ret) { | ||
dev_warn(&pdev->dev, | ||
"Failed to add device for DVSEC id %d\n", | ||
header.id); | ||
continue; | ||
} | ||
|
||
found_devices = true; | ||
} while (true); | ||
|
||
if (!found_devices) | ||
return -ENODEV; | ||
|
||
pm_runtime_put(&pdev->dev); | ||
pm_runtime_allow(&pdev->dev); | ||
|
||
return 0; | ||
} | ||
|
||
static void pmt_pci_remove(struct pci_dev *pdev) | ||
{ | ||
pm_runtime_forbid(&pdev->dev); | ||
pm_runtime_get_sync(&pdev->dev); | ||
} | ||
|
||
#define PCI_DEVICE_ID_INTEL_PMT_ADL 0x467d | ||
#define PCI_DEVICE_ID_INTEL_PMT_OOBMSM 0x09a7 | ||
#define PCI_DEVICE_ID_INTEL_PMT_TGL 0x9a0d | ||
static const struct pci_device_id pmt_pci_ids[] = { | ||
{ PCI_DEVICE_DATA(INTEL, PMT_ADL, &tgl_info) }, | ||
{ PCI_DEVICE_DATA(INTEL, PMT_OOBMSM, NULL) }, | ||
{ PCI_DEVICE_DATA(INTEL, PMT_TGL, &tgl_info) }, | ||
{ } | ||
}; | ||
MODULE_DEVICE_TABLE(pci, pmt_pci_ids); | ||
|
||
static struct pci_driver pmt_pci_driver = { | ||
.name = "intel-pmt", | ||
.id_table = pmt_pci_ids, | ||
.probe = pmt_pci_probe, | ||
.remove = pmt_pci_remove, | ||
}; | ||
module_pci_driver(pmt_pci_driver); | ||
|
||
MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>"); | ||
MODULE_DESCRIPTION("Intel Platform Monitoring Technology PMT driver"); | ||
MODULE_LICENSE("GPL v2"); |
Oops, something went wrong.