forked from mirrors/linux
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
...
513 lines
13 KiB
C
513 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");
|