mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 05:26:07 +00:00
088e0c1885
Highlights: - AMD PMC and PMF drivers: - Numerous bugfixes - Intel Speed Select Technology (ISST): - TPMI (Topology Aware Register and PM Capsule Interface) support for ISST support on upcoming processor models - Various other improvements / new hw support - tools/intel-speed-select: TPMI support + other improvements - Intel In Field Scan (IFS): - Add Array Bist test support - New drivers: - intel_bytcrc_pwrsrc Crystal Cove PMIC pwrsrc / reset-reason driver - lenovo-ymc Yoga Mode Control driver for reporting SW_TABLET_MODE - msi-ec Driver for MSI laptop EC features like battery charging limits - apple-gmux: - Support for new MMIO based models (T2 Macs) - Honor acpi_backlight= auto-detect-code + kernel cmdline option to switch between gmux and apple_bl backlight drivers and remove own custom handling for this - x86-android-tablets: Refactor / cleanup + new hw support - Miscellaneous other cleanups / fixes The following is an automated git shortlog grouped by driver: Add driver for Yoga Tablet Mode switch: - Add driver for Yoga Tablet Mode switch Add intel_bytcrc_pwrsrc driver: - Add intel_bytcrc_pwrsrc driver Add new msi-ec driver: - Add new msi-ec driver Documentation/ABI: - Update IFS ABI doc ISST: - unlock on error path in tpmi_sst_init() - Add suspend/resume callbacks - Add SST-TF support via TPMI - Add SST-BF support via TPMI - Add SST-PP support via TPMI - Add SST-CP support via TPMI - Parse SST MMIO and update instance - Enumerate TPMI SST and create framework - Add support for MSR 0x54 - Add API version of the target - Add IOCTL default callback - Add TPMI target Merge remote-tracking branch 'intel-speed-select/intel-sst' into review-hans: - Merge remote-tracking branch 'intel-speed-select/intel-sst' into review-hans Merge tag 'ib-pdx86-backlight-6.4' into review-hans: - Merge tag 'ib-pdx86-backlight-6.4' into review-hans Move ideapad ACPI helpers to a new header: - Move ideapad ACPI helpers to a new header acer-wmi: - Convert to platform remove callback returning void acerhdf: - Remove unneeded semicolon adv_swbutton: - Convert to platform remove callback returning void amilo-rfkill: - Convert to platform remove callback returning void apple-gmux: - Fix iomem_base __iomem annotation - return -EFAULT if copy fails - Update apple_gmux_detect documentation - Add acpi_video_get_backlight_type() check - add debugfs interface - support MMIO gmux on T2 Macs - refactor gmux types - use first bit to check switch state backlight: - apple_bl: Use acpi_video_get_backlight_type() barco-p50-gpio: - Convert to platform remove callback returning void classmate: - mark SPI related data as maybe unused compal-laptop: - Convert to platform remove callback returning void dell: - dell-smo8800: Convert to platform remove callback returning void - dcdbas: Convert to platform remove callback returning void dell-laptop: - Register ctl-led for speaker-mute hp: - tc1100-wmi: Convert to platform remove callback returning void - hp_accel: Convert to platform remove callback returning void huawei-wmi: - Convert to platform remove callback returning void ideapad-laptop: - Convert to platform remove callback returning void intel: - vbtn: Convert to platform remove callback returning void - telemetry: pltdrv: Convert to platform remove callback returning void - pmc: core: Convert to platform remove callback returning void - mrfld_pwrbtn: Convert to platform remove callback returning void - int3472: discrete: Convert to platform remove callback returning void - int1092: intel_sar: Convert to platform remove callback returning void - int0002_vgpio: Convert to platform remove callback returning void - hid: Convert to platform remove callback returning void - chtwc_int33fe: Convert to platform remove callback returning void - chtdc_ti_pwrbtn: Convert to platform remove callback returning void - bxtwc_tmu: Convert to platform remove callback returning void intel-uncore-freq: - Add client processors mlxbf-bootctl: - Add sysfs file for BlueField boot fifo pcengines-apuv2: - Drop platform:pcengines-apuv2 module-alias platform/mellanox: - add firmware reset support platform/olpc: - olpc-xo175-ec: Use SPI device ID data to bind device platform/surface: - aggregator_registry: Add support for tablet-mode switch on Surface Pro 9 - aggregator_tabletsw: Add support for Type-Cover posture source - aggregator_tabletsw: Properly handle different posture source IDs platform/x86/amd: - pmc: provide user message where s0ix is not supported - pmc: Remove __maybe_unused from amd_pmc_suspend_handler() - pmc: Convert to platform remove callback returning void - pmc: Fix memory leak in amd_pmc_stb_debugfs_open_v2() - pmc: Move out of BIOS SMN pair for STB init - pmc: Utilize SMN index 0 for driver probe - pmc: Move idlemask check into `amd_pmc_idlemask_read` - pmc: Don't dump data after resume from s0i3 on picasso - pmc: Hide SMU version and program attributes for Picasso - pmc: Don't try to read SMU version on Picasso - pmf: core: Convert to platform remove callback returning void - hsmp: Convert to platform remove callback returning void platform/x86/amd/pmf: - Move out of BIOS SMN pair for driver probe platform/x86/intel: - vsec: Use intel_vsec_dev_release() to simplify init() error cleanup - vsec: Explicitly enable capabilities platform/x86/intel/ifs: - Update IFS doc - Implement Array BIST test - Sysfs interface for Array BIST - Introduce Array Scan test to IFS - IFS cleanup - Reorganize driver data - Separate ifs_pkg_auth from ifs_data platform/x86/intel/pmc/mtl: - Put GNA/IPU/VPU devices in D3 platform/x86/intel/pmt: - Ignore uninitialized entries - Add INTEL_PMT module namespace platform/x86/intel/sdsi: - Change mailbox timeout samsung-q10: - Convert to platform remove callback returning void serial-multi-instantiate: - Convert to platform remove callback returning void sony: - mark SPI related data as maybe unused think-lmi: - Remove unnecessary casts for attributes - Remove custom kobject sysfs_ops - Properly interpret return value of tlmi_setting thinkpad_acpi: - Fix Embedded Controller access on X380 Yoga tools/power/x86/intel-speed-select: - Update version - Change TRL display for Emerald Rapids - Identify Emerald Rapids - Display AMX base frequency - Use cgroup v2 isolation - Add missing free cpuset - Fix clos-max display with TPMI I/F - Add cpu id check - Avoid setting duplicate tdp level - Remove cpu mask display for non-cpu power domain - Hide invalid TRL level - Display fact info for non-cpu power domain - Show level 0 name for new api_version - Prevent cpu clos config for non-cpu power domain - Allow display non-cpu power domain info - Display amx_p1 and cooling_type - Display punit info - Introduce TPMI interface support - Get punit core mapping information - Introduce api_version helper - Support large clos_min/max - Introduce is_debug_enabled() - Allow api_version based platform callbacks - Move send_mbox_cmd to isst-core-mbox.c - Abstract adjust_uncore_freq - Abstract read_pm_config - Abstract clos_associate - Abstract clos_get_assoc_status - Abstract set_clos - Abstract pm_get_clos - Abstract pm_qos_config - Abstract get_clos_information - Abstract get_get_trls - Enhance get_tdp_info - Abstract get_uncore_p0_p1_info - Abstract get_fact_info - Abstract set_pbf_fact_status - Remove isst_get_pbf_info_complete - Abstract get_pbf_info - Abstract set_tdp_level - Abstract get_trl_bucket_info - Abstract get_get_trl - Abstract get_coremask_info - Abstract get_tjmax_info - Move code right before its caller - Abstract get_pwr_info - Abstract get_tdp_info - Abstract get_ctdp_control - Abstract get_config_levels - Abstract is_punit_valid - Introduce isst-core-mbox.c - Always invoke isst_fill_platform_info - Introduce isst_get_disp_freq_multiplier - Move mbox functions to isst-core.c - Improve isst_print_extended_platform_info - Rename for_each_online_package_in_set - Introduce support for multi-punit - Introduce isst_is_punit_valid() - Introduce punit to isst_id - Follow TRL nameing for FACT info - Unify TRL levels wmi: - Convert to platform remove callback returning void x86-android-tablets: - Add accelerometer support for Yoga Tablet 2 1050/830 series - Add "yogabook-touch-kbd-digitizer-switch" pdev for Lenovo Yoga Book - Add Wacom digitizer info for Lenovo Yoga Book - Update Yoga Book HiDeep touchscreen comment - Add Lenovo Yoga Book X90F/L data - Share lp855x_platform_data between different models - Use LP8557 in direct mode on both the Yoga 830 and the 1050 - Add depends on PMIC_OPREGION - Lenovo Yoga Book match is for YB1-X91 models only - Add LID switch support for Yoga Tablet 2 1050/830 series - Add backlight ctrl for Lenovo Yoga Tab 3 Pro YT3-X90F - Add touchscreen support for Lenovo Yoga Tab 3 Pro YT3-X90F - Add support for the Dolby button on Peaq C1010 - Add gpio_keys support to x86_android_tablet_init() - Move remaining tablets to other.c - Move Lenovo tablets to their own file - Move Asus tablets to their own file - Move shared power-supply fw-nodes to a separate file - Move DMI match table into its own dmi.c file - Move core code into new core.c file - Move into its own subdir - Add Acer Iconia One 7 B1-750 data x86/include/asm/msr-index.h: - Add IFS Array test bits xo1-rfkill: - Convert to platform remove callback returning void -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmRGmK4UHGhkZWdvZWRl QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9yBCAf+PebzfccC2ABHq+nFGSok18beRtFf fGs9NI21Mjdbhhy+KsKddgZceh7pbdcaIznuka3TZAK0UXcHRe30X3eoDvSCk9YW Xj/Uf3ExsipNh1Ung+Q1qTWtzUw7XdJWqMZ5HxlUI2ZlmSTAIOyZBpSEPrK052oi lAbSqrnB1DEh1qYV4Q7g71R82iAR791DAH1dsDZwC1Zb6KK6fxI/zQhw4JP1XSCs htE5RFUzPWiXG2ou5t6Nteju/QqEaCoIS7z7ZK/SgWcLlPxeksxwso3obI/U8PvD JMmMiY4VFzizuGqTZHiy/EtKXo1pq+fOcMEqSuaaDfcYgdHmLm0OIU12Ig== =51xc -----END PGP SIGNATURE----- Merge tag 'platform-drivers-x86-v6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86 Pull x86 platform driver updates from Hans de Goede: - AMD PMC and PMF drivers: - Numerous bugfixes - Intel Speed Select Technology (ISST): - TPMI (Topology Aware Register and PM Capsule Interface) support for ISST support on upcoming processor models - Various other improvements / new hw support - tools/intel-speed-select: TPMI support + other improvements - Intel In Field Scan (IFS): - Add Array Bist test support - New drivers: - intel_bytcrc_pwrsrc Crystal Cove PMIC pwrsrc / reset-reason driver - lenovo-ymc Yoga Mode Control driver for reporting SW_TABLET_MODE - msi-ec Driver for MSI laptop EC features like battery charging limits - apple-gmux: - Support for new MMIO based models (T2 Macs) - Honor acpi_backlight= auto-detect-code + kernel cmdline option to switch between gmux and apple_bl backlight drivers and remove own custom handling for this - x86-android-tablets: Refactor / cleanup + new hw support - Miscellaneous other cleanups / fixes * tag 'platform-drivers-x86-v6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (178 commits) platform/x86: x86-android-tablets: Add accelerometer support for Yoga Tablet 2 1050/830 series platform/x86: x86-android-tablets: Add "yogabook-touch-kbd-digitizer-switch" pdev for Lenovo Yoga Book platform/x86: x86-android-tablets: Add Wacom digitizer info for Lenovo Yoga Book platform/x86: x86-android-tablets: Update Yoga Book HiDeep touchscreen comment platform/x86: thinkpad_acpi: Fix Embedded Controller access on X380 Yoga platform/x86/intel/sdsi: Change mailbox timeout platform/x86/intel/pmt: Ignore uninitialized entries platform/x86: amd: pmc: provide user message where s0ix is not supported platform/x86/amd: pmc: Fix memory leak in amd_pmc_stb_debugfs_open_v2() mlxbf-bootctl: Add sysfs file for BlueField boot fifo platform/x86: amd: pmc: Remove __maybe_unused from amd_pmc_suspend_handler() platform/x86/intel/pmc/mtl: Put GNA/IPU/VPU devices in D3 platform/x86/amd: pmc: Move out of BIOS SMN pair for STB init platform/x86/amd: pmc: Utilize SMN index 0 for driver probe platform/x86/amd: pmc: Move idlemask check into `amd_pmc_idlemask_read` platform/x86/amd: pmc: Don't dump data after resume from s0i3 on picasso platform/x86/amd: pmc: Hide SMU version and program attributes for Picasso platform/x86/amd: pmc: Don't try to read SMU version on Picasso platform/x86/amd/pmf: Move out of BIOS SMN pair for driver probe platform/x86: intel-uncore-freq: Add client processors ...
514 lines
13 KiB
C
514 lines
13 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Intel Vendor Specific Extended Capabilities auxiliary bus driver
|
|
*
|
|
* Copyright (c) 2021, Intel Corporation.
|
|
* All Rights Reserved.
|
|
*
|
|
* Author: David E. Box <david.e.box@linux.intel.com>
|
|
*
|
|
* This driver discovers and creates auxiliary devices for Intel defined PCIe
|
|
* "Vendor Specific" and "Designated Vendor Specific" Extended Capabilities,
|
|
* VSEC and DVSEC respectively. The driver supports features on specific PCIe
|
|
* endpoints that exist primarily to expose them.
|
|
*/
|
|
|
|
#include <linux/auxiliary_bus.h>
|
|
#include <linux/bits.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/idr.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/types.h>
|
|
|
|
#include "vsec.h"
|
|
|
|
/* Intel DVSEC 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 TABLE_OFFSET_SHIFT 3
|
|
#define PMT_XA_START 0
|
|
#define PMT_XA_MAX INT_MAX
|
|
#define PMT_XA_LIMIT XA_LIMIT(PMT_XA_START, PMT_XA_MAX)
|
|
|
|
static DEFINE_IDA(intel_vsec_ida);
|
|
static DEFINE_IDA(intel_vsec_sdsi_ida);
|
|
static DEFINE_XARRAY_ALLOC(auxdev_array);
|
|
|
|
/**
|
|
* struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
|
|
* @rev: Revision ID of the VSEC/DVSEC register space
|
|
* @length: Length of the VSEC/DVSEC register space
|
|
* @id: ID of the feature
|
|
* @num_entries: Number of instances of the feature
|
|
* @entry_size: Size of the discovery table for each feature
|
|
* @tbir: BAR containing the discovery tables
|
|
* @offset: BAR offset of start of the first discovery table
|
|
*/
|
|
struct intel_vsec_header {
|
|
u8 rev;
|
|
u16 length;
|
|
u16 id;
|
|
u8 num_entries;
|
|
u8 entry_size;
|
|
u8 tbir;
|
|
u32 offset;
|
|
};
|
|
|
|
enum intel_vsec_id {
|
|
VSEC_ID_TELEMETRY = 2,
|
|
VSEC_ID_WATCHER = 3,
|
|
VSEC_ID_CRASHLOG = 4,
|
|
VSEC_ID_SDSI = 65,
|
|
VSEC_ID_TPMI = 66,
|
|
};
|
|
|
|
static const char *intel_vsec_name(enum intel_vsec_id id)
|
|
{
|
|
switch (id) {
|
|
case VSEC_ID_TELEMETRY:
|
|
return "telemetry";
|
|
|
|
case VSEC_ID_WATCHER:
|
|
return "watcher";
|
|
|
|
case VSEC_ID_CRASHLOG:
|
|
return "crashlog";
|
|
|
|
case VSEC_ID_SDSI:
|
|
return "sdsi";
|
|
|
|
case VSEC_ID_TPMI:
|
|
return "tpmi";
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static bool intel_vsec_supported(u16 id, unsigned long caps)
|
|
{
|
|
switch (id) {
|
|
case VSEC_ID_TELEMETRY:
|
|
return !!(caps & VSEC_CAP_TELEMETRY);
|
|
case VSEC_ID_WATCHER:
|
|
return !!(caps & VSEC_CAP_WATCHER);
|
|
case VSEC_ID_CRASHLOG:
|
|
return !!(caps & VSEC_CAP_CRASHLOG);
|
|
case VSEC_ID_SDSI:
|
|
return !!(caps & VSEC_CAP_SDSI);
|
|
case VSEC_ID_TPMI:
|
|
return !!(caps & VSEC_CAP_TPMI);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static void intel_vsec_remove_aux(void *data)
|
|
{
|
|
auxiliary_device_delete(data);
|
|
auxiliary_device_uninit(data);
|
|
}
|
|
|
|
static DEFINE_MUTEX(vsec_ida_lock);
|
|
|
|
static void intel_vsec_dev_release(struct device *dev)
|
|
{
|
|
struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(dev);
|
|
|
|
mutex_lock(&vsec_ida_lock);
|
|
ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id);
|
|
mutex_unlock(&vsec_ida_lock);
|
|
|
|
kfree(intel_vsec_dev->resource);
|
|
kfree(intel_vsec_dev);
|
|
}
|
|
|
|
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;
|
|
|
|
mutex_lock(&vsec_ida_lock);
|
|
ret = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL);
|
|
mutex_unlock(&vsec_ida_lock);
|
|
if (ret < 0) {
|
|
kfree(intel_vsec_dev->resource);
|
|
kfree(intel_vsec_dev);
|
|
return ret;
|
|
}
|
|
|
|
if (!parent)
|
|
parent = &pdev->dev;
|
|
|
|
auxdev->id = ret;
|
|
auxdev->name = name;
|
|
auxdev->dev.parent = parent;
|
|
auxdev->dev.release = intel_vsec_dev_release;
|
|
|
|
ret = auxiliary_device_init(auxdev);
|
|
if (ret < 0) {
|
|
intel_vsec_dev_release(&auxdev->dev);
|
|
return ret;
|
|
}
|
|
|
|
ret = auxiliary_device_add(auxdev);
|
|
if (ret < 0) {
|
|
auxiliary_device_uninit(auxdev);
|
|
return ret;
|
|
}
|
|
|
|
ret = devm_add_action_or_reset(parent, intel_vsec_remove_aux,
|
|
auxdev);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
/* Add auxdev to list */
|
|
ret = xa_alloc(&auxdev_array, &id, intel_vsec_dev, PMT_XA_LIMIT,
|
|
GFP_KERNEL);
|
|
if (ret)
|
|
return ret;
|
|
|
|
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)
|
|
{
|
|
struct intel_vsec_device *intel_vsec_dev;
|
|
struct resource *res, *tmp;
|
|
unsigned long quirks = info->quirks;
|
|
int i;
|
|
|
|
if (!intel_vsec_supported(header->id, info->caps))
|
|
return -EINVAL;
|
|
|
|
if (!header->num_entries) {
|
|
dev_dbg(&pdev->dev, "Invalid 0 entry count for header id %d\n", header->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!header->entry_size) {
|
|
dev_dbg(&pdev->dev, "Invalid 0 entry size for header id %d\n", header->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
intel_vsec_dev = kzalloc(sizeof(*intel_vsec_dev), GFP_KERNEL);
|
|
if (!intel_vsec_dev)
|
|
return -ENOMEM;
|
|
|
|
res = kcalloc(header->num_entries, sizeof(*res), GFP_KERNEL);
|
|
if (!res) {
|
|
kfree(intel_vsec_dev);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (quirks & VSEC_QUIRK_TABLE_SHIFT)
|
|
header->offset >>= TABLE_OFFSET_SHIFT;
|
|
|
|
/*
|
|
* The DVSEC/VSEC contains the starting offset and count for a block of
|
|
* discovery tables. Create a resource array of these tables to the
|
|
* auxiliary device driver.
|
|
*/
|
|
for (i = 0, tmp = res; i < header->num_entries; i++, tmp++) {
|
|
tmp->start = pdev->resource[header->tbir].start +
|
|
header->offset + i * (header->entry_size * sizeof(u32));
|
|
tmp->end = tmp->start + (header->entry_size * sizeof(u32)) - 1;
|
|
tmp->flags = IORESOURCE_MEM;
|
|
}
|
|
|
|
intel_vsec_dev->pcidev = pdev;
|
|
intel_vsec_dev->resource = res;
|
|
intel_vsec_dev->num_resources = header->num_entries;
|
|
intel_vsec_dev->info = info;
|
|
|
|
if (header->id == VSEC_ID_SDSI)
|
|
intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
|
|
else
|
|
intel_vsec_dev->ida = &intel_vsec_ida;
|
|
|
|
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,
|
|
struct intel_vsec_platform_info *info)
|
|
{
|
|
struct intel_vsec_header **header = info->headers;
|
|
bool have_devices = false;
|
|
int ret;
|
|
|
|
for ( ; *header; header++) {
|
|
ret = intel_vsec_add_dev(pdev, *header, info);
|
|
if (ret)
|
|
dev_info(&pdev->dev, "Could not add device for VSEC id %d\n",
|
|
(*header)->id);
|
|
else
|
|
have_devices = true;
|
|
}
|
|
|
|
return have_devices;
|
|
}
|
|
|
|
static bool intel_vsec_walk_dvsec(struct pci_dev *pdev,
|
|
struct intel_vsec_platform_info *info)
|
|
{
|
|
bool have_devices = false;
|
|
int pos = 0;
|
|
|
|
do {
|
|
struct intel_vsec_header header;
|
|
u32 table, hdr;
|
|
u16 vid;
|
|
int ret;
|
|
|
|
pos = pci_find_next_ext_capability(pdev, pos, PCI_EXT_CAP_ID_DVSEC);
|
|
if (!pos)
|
|
break;
|
|
|
|
pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER1, &hdr);
|
|
vid = PCI_DVSEC_HEADER1_VID(hdr);
|
|
if (vid != PCI_VENDOR_ID_INTEL)
|
|
continue;
|
|
|
|
/* Support only revision 1 */
|
|
header.rev = PCI_DVSEC_HEADER1_REV(hdr);
|
|
if (header.rev != 1) {
|
|
dev_info(&pdev->dev, "Unsupported DVSEC revision %d\n", header.rev);
|
|
continue;
|
|
}
|
|
|
|
header.length = PCI_DVSEC_HEADER1_LEN(hdr);
|
|
|
|
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);
|
|
|
|
pci_read_config_dword(pdev, pos + PCI_DVSEC_HEADER2, &hdr);
|
|
header.id = PCI_DVSEC_HEADER2_ID(hdr);
|
|
|
|
ret = intel_vsec_add_dev(pdev, &header, info);
|
|
if (ret)
|
|
continue;
|
|
|
|
have_devices = true;
|
|
} while (true);
|
|
|
|
return have_devices;
|
|
}
|
|
|
|
static bool intel_vsec_walk_vsec(struct pci_dev *pdev,
|
|
struct intel_vsec_platform_info *info)
|
|
{
|
|
bool have_devices = false;
|
|
int pos = 0;
|
|
|
|
do {
|
|
struct intel_vsec_header header;
|
|
u32 table, hdr;
|
|
int ret;
|
|
|
|
pos = pci_find_next_ext_capability(pdev, pos, PCI_EXT_CAP_ID_VNDR);
|
|
if (!pos)
|
|
break;
|
|
|
|
pci_read_config_dword(pdev, pos + PCI_VNDR_HEADER, &hdr);
|
|
|
|
/* Support only revision 1 */
|
|
header.rev = PCI_VNDR_HEADER_REV(hdr);
|
|
if (header.rev != 1) {
|
|
dev_info(&pdev->dev, "Unsupported VSEC revision %d\n", header.rev);
|
|
continue;
|
|
}
|
|
|
|
header.id = PCI_VNDR_HEADER_ID(hdr);
|
|
header.length = PCI_VNDR_HEADER_LEN(hdr);
|
|
|
|
/* entry, size, and table offset are the same as DVSEC */
|
|
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 = intel_vsec_add_dev(pdev, &header, info);
|
|
if (ret)
|
|
continue;
|
|
|
|
have_devices = true;
|
|
} while (true);
|
|
|
|
return have_devices;
|
|
}
|
|
|
|
static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
{
|
|
struct intel_vsec_platform_info *info;
|
|
bool have_devices = false;
|
|
int ret;
|
|
|
|
ret = pcim_enable_device(pdev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
pci_save_state(pdev);
|
|
info = (struct intel_vsec_platform_info *)id->driver_data;
|
|
if (!info)
|
|
return -EINVAL;
|
|
|
|
if (intel_vsec_walk_dvsec(pdev, info))
|
|
have_devices = true;
|
|
|
|
if (intel_vsec_walk_vsec(pdev, info))
|
|
have_devices = true;
|
|
|
|
if (info && (info->quirks & VSEC_QUIRK_NO_DVSEC) &&
|
|
intel_vsec_walk_header(pdev, info))
|
|
have_devices = true;
|
|
|
|
if (!have_devices)
|
|
return -ENODEV;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* DG1 info */
|
|
static struct intel_vsec_header dg1_header = {
|
|
.length = 0x10,
|
|
.id = 2,
|
|
.num_entries = 1,
|
|
.entry_size = 3,
|
|
.tbir = 0,
|
|
.offset = 0x466000,
|
|
};
|
|
|
|
static struct intel_vsec_header *dg1_headers[] = {
|
|
&dg1_header,
|
|
NULL
|
|
};
|
|
|
|
static const struct intel_vsec_platform_info dg1_info = {
|
|
.caps = VSEC_CAP_TELEMETRY,
|
|
.headers = dg1_headers,
|
|
.quirks = VSEC_QUIRK_NO_DVSEC | VSEC_QUIRK_EARLY_HW,
|
|
};
|
|
|
|
/* MTL info */
|
|
static const struct intel_vsec_platform_info mtl_info = {
|
|
.caps = VSEC_CAP_TELEMETRY,
|
|
};
|
|
|
|
/* OOBMSM info */
|
|
static const struct intel_vsec_platform_info oobmsm_info = {
|
|
.caps = VSEC_CAP_TELEMETRY | VSEC_CAP_SDSI | VSEC_CAP_TPMI,
|
|
};
|
|
|
|
/* TGL info */
|
|
static const struct intel_vsec_platform_info tgl_info = {
|
|
.caps = VSEC_CAP_TELEMETRY,
|
|
.quirks = VSEC_QUIRK_TABLE_SHIFT | VSEC_QUIRK_EARLY_HW,
|
|
};
|
|
|
|
#define PCI_DEVICE_ID_INTEL_VSEC_ADL 0x467d
|
|
#define PCI_DEVICE_ID_INTEL_VSEC_DG1 0x490e
|
|
#define PCI_DEVICE_ID_INTEL_VSEC_MTL_M 0x7d0d
|
|
#define PCI_DEVICE_ID_INTEL_VSEC_MTL_S 0xad0d
|
|
#define PCI_DEVICE_ID_INTEL_VSEC_OOBMSM 0x09a7
|
|
#define PCI_DEVICE_ID_INTEL_VSEC_RPL 0xa77d
|
|
#define PCI_DEVICE_ID_INTEL_VSEC_TGL 0x9a0d
|
|
static const struct pci_device_id intel_vsec_pci_ids[] = {
|
|
{ PCI_DEVICE_DATA(INTEL, VSEC_ADL, &tgl_info) },
|
|
{ PCI_DEVICE_DATA(INTEL, VSEC_DG1, &dg1_info) },
|
|
{ PCI_DEVICE_DATA(INTEL, VSEC_MTL_M, &mtl_info) },
|
|
{ PCI_DEVICE_DATA(INTEL, VSEC_MTL_S, &mtl_info) },
|
|
{ PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, &oobmsm_info) },
|
|
{ PCI_DEVICE_DATA(INTEL, VSEC_RPL, &tgl_info) },
|
|
{ PCI_DEVICE_DATA(INTEL, VSEC_TGL, &tgl_info) },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, intel_vsec_pci_ids);
|
|
|
|
static pci_ers_result_t intel_vsec_pci_error_detected(struct pci_dev *pdev,
|
|
pci_channel_state_t state)
|
|
{
|
|
pci_ers_result_t status = PCI_ERS_RESULT_NEED_RESET;
|
|
|
|
dev_info(&pdev->dev, "PCI error detected, state %d", state);
|
|
|
|
if (state == pci_channel_io_perm_failure)
|
|
status = PCI_ERS_RESULT_DISCONNECT;
|
|
else
|
|
pci_disable_device(pdev);
|
|
|
|
return status;
|
|
}
|
|
|
|
static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev)
|
|
{
|
|
struct intel_vsec_device *intel_vsec_dev;
|
|
pci_ers_result_t status = PCI_ERS_RESULT_DISCONNECT;
|
|
const struct pci_device_id *pci_dev_id;
|
|
unsigned long index;
|
|
|
|
dev_info(&pdev->dev, "Resetting PCI slot\n");
|
|
|
|
msleep(2000);
|
|
if (pci_enable_device(pdev)) {
|
|
dev_info(&pdev->dev,
|
|
"Failed to re-enable PCI device after reset.\n");
|
|
goto out;
|
|
}
|
|
|
|
status = PCI_ERS_RESULT_RECOVERED;
|
|
|
|
xa_for_each(&auxdev_array, index, intel_vsec_dev) {
|
|
/* check if pdev doesn't match */
|
|
if (pdev != intel_vsec_dev->pcidev)
|
|
continue;
|
|
devm_release_action(&pdev->dev, intel_vsec_remove_aux,
|
|
&intel_vsec_dev->auxdev);
|
|
}
|
|
pci_disable_device(pdev);
|
|
pci_restore_state(pdev);
|
|
pci_dev_id = pci_match_id(intel_vsec_pci_ids, pdev);
|
|
intel_vsec_pci_probe(pdev, pci_dev_id);
|
|
|
|
out:
|
|
return status;
|
|
}
|
|
|
|
static void intel_vsec_pci_resume(struct pci_dev *pdev)
|
|
{
|
|
dev_info(&pdev->dev, "Done resuming PCI device\n");
|
|
}
|
|
|
|
static const struct pci_error_handlers intel_vsec_pci_err_handlers = {
|
|
.error_detected = intel_vsec_pci_error_detected,
|
|
.slot_reset = intel_vsec_pci_slot_reset,
|
|
.resume = intel_vsec_pci_resume,
|
|
};
|
|
|
|
static struct pci_driver intel_vsec_pci_driver = {
|
|
.name = "intel_vsec",
|
|
.id_table = intel_vsec_pci_ids,
|
|
.probe = intel_vsec_pci_probe,
|
|
.err_handler = &intel_vsec_pci_err_handlers,
|
|
};
|
|
module_pci_driver(intel_vsec_pci_driver);
|
|
|
|
MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
|
|
MODULE_DESCRIPTION("Intel Extended Capabilities auxiliary bus driver");
|
|
MODULE_LICENSE("GPL v2");
|