Commit aa47ad3f authored by David E. Box's avatar David E. Box Committed by Lee Jones

mfd: intel_pmt: Add support for DG1

Adds PMT Telemetry aggregator support for the DG1 graphics PCIe card. The
device does not have the DVSEC region in its PCI config space so hard
code the discovery table data in the driver. Also requires a fix for DG1
in the Telemetry driver for how the ACCESS_TYPE field is used.
Signed-off-by: default avatarDavid E. Box <david.e.box@linux.intel.com>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent a1a5c1c3
...@@ -49,10 +49,14 @@ enum pmt_quirks { ...@@ -49,10 +49,14 @@ enum pmt_quirks {
/* Use shift instead of mask to read discovery table offset */ /* Use shift instead of mask to read discovery table offset */
PMT_QUIRK_TABLE_SHIFT = BIT(2), PMT_QUIRK_TABLE_SHIFT = BIT(2),
/* DVSEC not present (provided in driver data) */
PMT_QUIRK_NO_DVSEC = BIT(3),
}; };
struct pmt_platform_info { struct pmt_platform_info {
unsigned long quirks; unsigned long quirks;
struct intel_dvsec_header **capabilities;
}; };
static const struct pmt_platform_info tgl_info = { static const struct pmt_platform_info tgl_info = {
...@@ -60,6 +64,26 @@ static const struct pmt_platform_info tgl_info = { ...@@ -60,6 +64,26 @@ static const struct pmt_platform_info tgl_info = {
PMT_QUIRK_TABLE_SHIFT, PMT_QUIRK_TABLE_SHIFT,
}; };
/* DG1 Platform with DVSEC quirk*/
static struct intel_dvsec_header dg1_telemetry = {
.length = 0x10,
.id = 2,
.num_entries = 1,
.entry_size = 3,
.tbir = 0,
.offset = 0x466000,
};
static struct intel_dvsec_header *dg1_capabilities[] = {
&dg1_telemetry,
NULL
};
static const struct pmt_platform_info dg1_info = {
.quirks = PMT_QUIRK_NO_DVSEC,
.capabilities = dg1_capabilities,
};
static int pmt_add_dev(struct pci_dev *pdev, struct intel_dvsec_header *header, static int pmt_add_dev(struct pci_dev *pdev, struct intel_dvsec_header *header,
unsigned long quirks) unsigned long quirks)
{ {
...@@ -147,6 +171,22 @@ static int pmt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -147,6 +171,22 @@ static int pmt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (info) if (info)
quirks = info->quirks; quirks = info->quirks;
if (info && (info->quirks & PMT_QUIRK_NO_DVSEC)) {
struct intel_dvsec_header **header;
header = info->capabilities;
while (*header) {
ret = pmt_add_dev(pdev, *header, quirks);
if (ret)
dev_warn(&pdev->dev,
"Failed to add device for DVSEC id %d\n",
(*header)->id);
else
found_devices = true;
++header;
}
} else {
do { do {
struct intel_dvsec_header header; struct intel_dvsec_header header;
u32 table; u32 table;
...@@ -178,6 +218,7 @@ static int pmt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -178,6 +218,7 @@ static int pmt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
found_devices = true; found_devices = true;
} while (true); } while (true);
}
if (!found_devices) if (!found_devices)
return -ENODEV; return -ENODEV;
...@@ -195,10 +236,12 @@ static void pmt_pci_remove(struct pci_dev *pdev) ...@@ -195,10 +236,12 @@ static void pmt_pci_remove(struct pci_dev *pdev)
} }
#define PCI_DEVICE_ID_INTEL_PMT_ADL 0x467d #define PCI_DEVICE_ID_INTEL_PMT_ADL 0x467d
#define PCI_DEVICE_ID_INTEL_PMT_DG1 0x490e
#define PCI_DEVICE_ID_INTEL_PMT_OOBMSM 0x09a7 #define PCI_DEVICE_ID_INTEL_PMT_OOBMSM 0x09a7
#define PCI_DEVICE_ID_INTEL_PMT_TGL 0x9a0d #define PCI_DEVICE_ID_INTEL_PMT_TGL 0x9a0d
static const struct pci_device_id pmt_pci_ids[] = { static const struct pci_device_id pmt_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, PMT_ADL, &tgl_info) }, { PCI_DEVICE_DATA(INTEL, PMT_ADL, &tgl_info) },
{ PCI_DEVICE_DATA(INTEL, PMT_DG1, &dg1_info) },
{ PCI_DEVICE_DATA(INTEL, PMT_OOBMSM, NULL) }, { PCI_DEVICE_DATA(INTEL, PMT_OOBMSM, NULL) },
{ PCI_DEVICE_DATA(INTEL, PMT_TGL, &tgl_info) }, { PCI_DEVICE_DATA(INTEL, PMT_TGL, &tgl_info) },
{ } { }
......
...@@ -19,6 +19,28 @@ ...@@ -19,6 +19,28 @@
#define PMT_XA_MAX INT_MAX #define PMT_XA_MAX INT_MAX
#define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX) #define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX)
/*
* Early implementations of PMT on client platforms have some
* differences from the server platforms (which use the Out Of Band
* Management Services Module OOBMSM). This list tracks those
* platforms as needed to handle those differences. Newer client
* platforms are expected to be fully compatible with server.
*/
static const struct pci_device_id pmt_telem_early_client_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x467d) }, /* ADL */
{ PCI_VDEVICE(INTEL, 0x490e) }, /* DG1 */
{ PCI_VDEVICE(INTEL, 0x9a0d) }, /* TGL */
{ }
};
bool intel_pmt_is_early_client_hw(struct device *dev)
{
struct pci_dev *parent = to_pci_dev(dev->parent);
return !!pci_match_id(pmt_telem_early_client_pci_ids, parent);
}
EXPORT_SYMBOL_GPL(intel_pmt_is_early_client_hw);
/* /*
* sysfs * sysfs
*/ */
...@@ -147,6 +169,30 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry, ...@@ -147,6 +169,30 @@ static int intel_pmt_populate_entry(struct intel_pmt_entry *entry,
* base address = end of discovery region + base offset * base address = end of discovery region + base offset
*/ */
entry->base_addr = disc_res->end + 1 + header->base_offset; entry->base_addr = disc_res->end + 1 + header->base_offset;
/*
* Some hardware use a different calculation for the base address
* when access_type == ACCESS_LOCAL. On the these systems
* ACCCESS_LOCAL refers to an address in the same BAR as the
* header but at a fixed offset. But as the header address was
* supplied to the driver, we don't know which BAR it was in.
* So search for the bar whose range includes the header address.
*/
if (intel_pmt_is_early_client_hw(dev)) {
int i;
entry->base_addr = 0;
for (i = 0; i < 6; i++)
if (disc_res->start >= pci_resource_start(pci_dev, i) &&
(disc_res->start <= pci_resource_end(pci_dev, i))) {
entry->base_addr = pci_resource_start(pci_dev, i) +
header->base_offset;
break;
}
if (!entry->base_addr)
return -EINVAL;
}
break; break;
case ACCESS_BARID: case ACCESS_BARID:
/* /*
......
...@@ -44,6 +44,7 @@ struct intel_pmt_namespace { ...@@ -44,6 +44,7 @@ struct intel_pmt_namespace {
struct device *dev); struct device *dev);
}; };
bool intel_pmt_is_early_client_hw(struct device *dev);
int intel_pmt_dev_create(struct intel_pmt_entry *entry, int intel_pmt_dev_create(struct intel_pmt_entry *entry,
struct intel_pmt_namespace *ns, struct intel_pmt_namespace *ns,
struct platform_device *pdev, int idx); struct platform_device *pdev, int idx);
......
...@@ -34,26 +34,6 @@ struct pmt_telem_priv { ...@@ -34,26 +34,6 @@ struct pmt_telem_priv {
struct intel_pmt_entry entry[]; struct intel_pmt_entry entry[];
}; };
/*
* Early implementations of PMT on client platforms have some
* differences from the server platforms (which use the Out Of Band
* Management Services Module OOBMSM). This list tracks those
* platforms as needed to handle those differences. Newer client
* platforms are expected to be fully compatible with server.
*/
static const struct pci_device_id pmt_telem_early_client_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x9a0d) }, /* TGL */
{ PCI_VDEVICE(INTEL, 0x467d) }, /* ADL */
{ }
};
static bool intel_pmt_is_early_client_hw(struct device *dev)
{
struct pci_dev *parent = to_pci_dev(dev->parent);
return !!pci_match_id(pmt_telem_early_client_pci_ids, parent);
}
static bool pmt_telem_region_overlaps(struct intel_pmt_entry *entry, static bool pmt_telem_region_overlaps(struct intel_pmt_entry *entry,
struct device *dev) struct device *dev)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment