Merge tag 'platform-drivers-x86-v6.5-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:
   - Various bugfixes
   - Improved debugging support

  Intel PMC:
   - Refactor to support hw with multiple PMCs
   - Various other improvements / new hw support

  Intel Speed Select Technology (ISST):
   - TPMI Uncore Frequency + Cluster Level Power Controls
   - Various bugfixes
   - tools/intel-speed-select: Misc improvements

  Dell-DDV: Add documentation

  INT3472 ACPI camera sensor glue code:
   - Evaluate device's _DSM method to control imaging clock
   - Drop the need to have a table with per sensor-model info

  Lenovo Yogabook:
   - Refactor / rework to also support Android models

  Think-LMI:
   - Multiple improvements and fixes

  WMI:
   - Add proper API documentation for the WMI bus

  x86-android-tablets:
   - Misc new hw support

  Miscellaneous other cleanups / fixes"

* tag 'platform-drivers-x86-v6.5-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (91 commits)
  platform/x86:intel/pmc: Add Meteor Lake IOE-M PMC related maps
  platform/x86:intel/pmc: Add Meteor Lake IOE-P PMC related maps
  platform/x86:intel/pmc: Use SSRAM to discover pwrm base address of primary PMC
  platform/x86:intel/pmc: Discover PMC devices
  platform/x86:intel/pmc: Enable debugfs multiple PMC support
  platform/x86:intel/pmc: Add support to handle multiple PMCs
  platform/x86:intel/pmc: Combine core_init() and core_configure()
  platform/x86:intel/pmc: Update maps for Meteor Lake P/M platforms
  platform/x86/intel: tpmi: Remove hardcoded unit and offset
  platform/x86: int3472: discrete: Log a warning if the pin-numbers don't match
  platform/x86: int3472: discrete: Use FIELD_GET() on the GPIO _DSM return value
  platform/x86: int3472: discrete: Add alternative "AVDD" regulator supply name
  platform/x86: int3472: discrete: Add support for 1 GPIO regulator shared between 2 sensors
  platform/x86: int3472: discrete: Remove sensor_config-s
  platform/x86: int3472: discrete: Drop GPIO remapping support
  platform/x86: apple-gmux: don't use be32_to_cpu and cpu_to_be32
  platform/x86/dell/dell-rbtn: Fix resources leaking on error path
  platform/x86: ISST: Fix usage counter
  platform/x86: ISST: Reset default callback on unregister
  platform/x86: int3472: Switch back to use struct i2c_driver's .probe()
  ...
This commit is contained in:
Linus Torvalds
2023-06-30 14:50:00 -07:00
70 changed files with 4517 additions and 955 deletions

View File

@@ -0,0 +1,7 @@
What: /sys/bus/wmi/devices/05901221-D566-11D1-B2F0-00A0C9062910[-X]/bmof
Date: Jun 2017
KernelVersion: 4.13
Description:
Binary MOF metadata used to decribe the details of available ACPI WMI interfaces.
See Documentation/wmi/devices/wmi-bmof.rst for details.

View File

@@ -3,19 +3,32 @@ Date: September 2022
KernelVersion: 6.1
Contact: Armin Wolf <W_Armin@gmx.de>
Description:
This file contains the contents of the fan sensor information buffer,
which contains fan sensor entries and a terminating character (0xFF).
This file contains the contents of the fan sensor information
buffer, which contains fan sensor entries and a terminating
character (0xFF).
Each fan sensor entry consists of three bytes with an unknown meaning,
interested people may use this file for reverse-engineering.
Each fan sensor entry contains:
- fan type (single byte)
- fan speed in RPM (two bytes, little endian)
See Documentation/wmi/devices/dell-wmi-ddv.rst for details.
What: /sys/kernel/debug/dell-wmi-ddv-<wmi_device_name>/thermal_sensor_information
Date: September 2022
KernelVersion: 6.1
Contact: Armin Wolf <W_Armin@gmx.de>
Description:
This file contains the contents of the thermal sensor information buffer,
which contains thermal sensor entries and a terminating character (0xFF).
This file contains the contents of the thermal sensor information
buffer, which contains thermal sensor entries and a terminating
character (0xFF).
Each thermal sensor entry consists of five bytes with an unknown meaning,
interested people may use this file for reverse-engineering.
Each thermal sensor entry contains:
- thermal type (single byte)
- current temperature (single byte)
- min. temperature (single byte)
- max. temperature (single byte)
- unknown field (single byte)
See Documentation/wmi/devices/dell-wmi-ddv.rst for details.

View File

@@ -243,8 +243,8 @@ Description:
index:
Used with HDD and NVME authentication to set the drive index
that is being referenced (e.g hdd0, hdd1 etc)
This attribute defaults to device 0.
that is being referenced (e.g hdd1, hdd2 etc)
This attribute defaults to device 1.
certificate, signature, save_signature:
These attributes are used for certificate based authentication. This is

View File

@@ -3,5 +3,7 @@ Date: September 2022
KernelVersion: 6.1
Contact: Armin Wolf <W_Armin@gmx.de>
Description:
Reports the Dell ePPID (electronic Dell Piece Part Identification)
Reports the Dell ePPID (electronic Piece Part Identification)
of the ACPI battery.
See Documentation/wmi/devices/dell-wmi-ddv.rst for details.

View File

@@ -75,3 +75,12 @@ KernelVersion: 6.4
Contact: "Liming Sun <limings@nvidia.com>"
Description:
The file used to access the BlueField boot fifo.
What: /sys/bus/platform/devices/MLNXBF04:00/rsh_log
Date: May 2023
KernelVersion: 6.4
Contact: "Liming Sun <limings@nvidia.com>"
Description:
The file used to write BlueField boot log with the format
"[INFO|WARN|ERR|ASSERT ]<msg>". Log level 'INFO' is used by
default if not specified.

View File

@@ -5,7 +5,7 @@
Intel Uncore Frequency Scaling
==============================
:Copyright: |copy| 2022 Intel Corporation
:Copyright: |copy| 2022-2023 Intel Corporation
:Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
@@ -58,3 +58,58 @@ Each package_*_die_* contains the following attributes:
``current_freq_khz``
This attribute is used to get the current uncore frequency.
SoCs with TPMI (Topology Aware Register and PM Capsule Interface)
-----------------------------------------------------------------
An SoC can contain multiple power domains with individual or collection
of mesh partitions. This partition is called fabric cluster.
Certain type of meshes will need to run at the same frequency, they will
be placed in the same fabric cluster. Benefit of fabric cluster is that it
offers a scalable mechanism to deal with partitioned fabrics in a SoC.
The current sysfs interface supports controls at package and die level.
This interface is not enough to support more granular control at
fabric cluster level.
SoCs with the support of TPMI (Topology Aware Register and PM Capsule
Interface), can have multiple power domains. Each power domain can
contain one or more fabric clusters.
To represent controls at fabric cluster level in addition to the
controls at package and die level (like systems without TPMI
support), sysfs is enhanced. This granular interface is presented in the
sysfs with directories names prefixed with "uncore". For example:
uncore00, uncore01 etc.
The scope of control is specified by attributes "package_id", "domain_id"
and "fabric_cluster_id" in the directory.
Attributes in each directory:
``domain_id``
This attribute is used to get the power domain id of this instance.
``fabric_cluster_id``
This attribute is used to get the fabric cluster id of this instance.
``package_id``
This attribute is used to get the package id of this instance.
The other attributes are same as presented at package_*_die_* level.
In most of current use cases, the "max_freq_khz" and "min_freq_khz"
is updated at "package_*_die_*" level. This model will be still supported
with the following approach:
When user uses controls at "package_*_die_*" level, then every fabric
cluster is affected in that package and die. For example: user changes
"max_freq_khz" in the package_00_die_00, then "max_freq_khz" for uncore*
directory with the same package id will be updated. In this case user can
still update "max_freq_khz" at each uncore* level, which is more restrictive.
Similarly, user can update "min_freq_khz" at "package_*_die_*" level
to apply at each uncore* level.
Support for "current_freq_khz" is available only at each fabric cluster
level (i.e., in uncore* directory).

View File

@@ -113,6 +113,7 @@ available subsections can be seen below.
xillybus
zorro
hte/index
wmi
.. only:: subproject and html

View File

@@ -0,0 +1,21 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
==============
WMI Driver API
==============
The WMI driver core supports a more modern bus-based interface for interacting
with WMI devices, and an older GUID-based interface. The latter interface is
considered to be deprecated, so new WMI drivers should generally avoid it since
it has some issues with multiple WMI devices and events sharing the same GUIDs
and/or notification IDs. The modern bus-based interface instead maps each
WMI device to a :c:type:`struct wmi_device <wmi_device>`, so it supports
WMI devices sharing GUIDs and/or notification IDs. Drivers can then register
a :c:type:`struct wmi_driver <wmi_driver>`, which will be bound to compatible
WMI devices by the driver core.
.. kernel-doc:: include/linux/wmi.h
:internal:
.. kernel-doc:: drivers/platform/x86/wmi.c
:export:

View File

@@ -71,3 +71,4 @@ Storage interfaces
scheduler/index
mhi/index
peci/index
wmi/index

View File

@@ -0,0 +1,96 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
==================
ACPI WMI interface
==================
The ACPI WMI interface is a proprietary extension of the ACPI specification made
by Microsoft to allow hardware vendors to embed WMI (Windows Management Instrumentation)
objects inside their ACPI firmware. Typical functions implemented over ACPI WMI
are hotkey events on modern notebooks and configuration of BIOS options.
PNP0C14 ACPI device
-------------------
Discovery of WMI objects is handled by defining ACPI devices with a PNP ID
of ``PNP0C14``. These devices will contain a set of ACPI buffers and methods
used for mapping and execution of WMI methods and/or queries. If there exist
multiple of such devices, then each device is required to have a
unique ACPI UID.
_WDG buffer
-----------
The ``_WDG`` buffer is used to discover WMI objects and is required to be
static. Its internal structure consists of data blocks with a size of 20 bytes,
containing the following data:
======= =============== =====================================================
Offset Size (in bytes) Content
======= =============== =====================================================
0x00 16 128 bit Variant 2 object GUID.
0x10 2 2 character method ID or single byte notification ID.
0x12 1 Object instance count.
0x13 1 Object flags.
======= =============== =====================================================
The WMI object flags control whether the method or notification ID is used:
- 0x1: Data block usage is expensive and must be explicitly enabled/disabled.
- 0x2: Data block contains WMI methods.
- 0x4: Data block contains ASCIZ string.
- 0x8: Data block describes a WMI event, use notification ID instead
of method ID.
Each WMI object GUID can appear multiple times inside a system.
The method/notification ID is used to construct the ACPI method names used for
interacting with the WMI object.
WQxx ACPI methods
-----------------
If a data block does not contain WMI methods, then its content can be retrieved
by this required ACPI method. The last two characters of the ACPI method name
are the method ID of the data block to query. Their single parameter is an
integer describing the instance which should be queried. This parameter can be
omitted if the data block contains only a single instance.
WSxx ACPI methods
-----------------
Similar to the ``WQxx`` ACPI methods, except that it is optional and takes an
additional buffer as its second argument. The instance argument also cannot
be omitted.
WMxx ACPI methods
-----------------
Used for executing WMI methods associated with a data block. The last two
characters of the ACPI method name are the method ID of the data block
containing the WMI methods. Their first parameter is a integer describing the
instance which methods should be executed. The second parameter is an integer
describing the WMI method ID to execute, and the third parameter is a buffer
containing the WMI method parameters. If the data block is marked as containing
an ASCIZ string, then this buffer should contain an ASCIZ string. The ACPI
method will return the result of the executed WMI method.
WExx ACPI methods
-----------------
Used for optionally enabling/disabling WMI events, the last two characters of
the ACPI method are the notification ID of the data block describing the WMI
event as hexadecimal value. Their first parameter is an integer with a value
of 0 if the WMI event should be disabled, other values will enable
the WMI event.
WCxx ACPI methods
-----------------
Similar to the ``WExx`` ACPI methods, except that it controls data collection
instead of events and thus the last two characters of the ACPI method name are
the method ID of the data block to enable/disable.
_WED ACPI method
----------------
Used to retrieve additional WMI event data, its single parameter is a integer
holding the notification ID of the event.

View File

@@ -0,0 +1,296 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
============================================
Dell DDV WMI interface driver (dell-wmi-ddv)
============================================
Introduction
============
Many Dell notebooks made after ~2020 support a WMI-based interface for
retrieving various system data like battery temperature, ePPID, diagostic data
and fan/thermal sensor data.
This interface is likely used by the `Dell Data Vault` software on Windows,
so it was called `DDV`. Currently the ``dell-wmi-ddv`` driver supports
version 2 and 3 of the interface, with support for new interface versions
easily added.
.. warning:: The interface is regarded as internal by Dell, so no vendor
documentation is available. All knowledge was thus obtained by
trial-and-error, please keep that in mind.
Dell ePPID (electronic Piece Part Identification)
=================================================
The Dell ePPID is used to uniquely identify components in Dell machines,
including batteries. It has a form similar to `CC-PPPPPP-MMMMM-YMD-SSSS-FFF`
and contains the following information:
* Country code of origin (CC).
* Part number with the first character being a filling number (PPPPPP).
* Manufacture Identification (MMMMM).
* Manufacturing Year/Month/Date (YMD) in base 36, with Y being the last digit
of the year.
* Manufacture Sequence Number (SSSS).
* Optional Firmware Version/Revision (FFF).
The `eppidtool <https://pypi.org/project/eppidtool>`_ python utility can be used
to decode and display this information.
All information regarding the Dell ePPID was gathered using Dell support
documentation and `this website <https://telcontar.net/KBK/Dell/date_codes>`_.
WMI interface description
=========================
The WMI interface description can be decoded from the embedded binary MOF (bmof)
data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility:
::
[WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{8A42EA14-4F2A-FD45-6422-0087F7A7E608}")]
class DDVWmiMethodFunction {
[key, read] string InstanceName;
[read] boolean Active;
[WmiMethodId(1), Implemented, read, write, Description("Return Battery Design Capacity.")] void BatteryDesignCapacity([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(2), Implemented, read, write, Description("Return Battery Full Charge Capacity.")] void BatteryFullChargeCapacity([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(3), Implemented, read, write, Description("Return Battery Manufacture Name.")] void BatteryManufactureName([in] uint32 arg2, [out] string argr);
[WmiMethodId(4), Implemented, read, write, Description("Return Battery Manufacture Date.")] void BatteryManufactureDate([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(5), Implemented, read, write, Description("Return Battery Serial Number.")] void BatterySerialNumber([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(6), Implemented, read, write, Description("Return Battery Chemistry Value.")] void BatteryChemistryValue([in] uint32 arg2, [out] string argr);
[WmiMethodId(7), Implemented, read, write, Description("Return Battery Temperature.")] void BatteryTemperature([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(8), Implemented, read, write, Description("Return Battery Current.")] void BatteryCurrent([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(9), Implemented, read, write, Description("Return Battery Voltage.")] void BatteryVoltage([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(10), Implemented, read, write, Description("Return Battery Manufacture Access(MA code).")] void BatteryManufactureAceess([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(11), Implemented, read, write, Description("Return Battery Relative State-Of-Charge.")] void BatteryRelativeStateOfCharge([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(12), Implemented, read, write, Description("Return Battery Cycle Count")] void BatteryCycleCount([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(13), Implemented, read, write, Description("Return Battery ePPID")] void BatteryePPID([in] uint32 arg2, [out] string argr);
[WmiMethodId(14), Implemented, read, write, Description("Return Battery Raw Analytics Start")] void BatteryeRawAnalyticsStart([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(15), Implemented, read, write, Description("Return Battery Raw Analytics")] void BatteryeRawAnalytics([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]);
[WmiMethodId(16), Implemented, read, write, Description("Return Battery Design Voltage.")] void BatteryDesignVoltage([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(17), Implemented, read, write, Description("Return Battery Raw Analytics A Block")] void BatteryeRawAnalyticsABlock([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]);
[WmiMethodId(18), Implemented, read, write, Description("Return Version.")] void ReturnVersion([in] uint32 arg2, [out] uint32 argr);
[WmiMethodId(32), Implemented, read, write, Description("Return Fan Sensor Information")] void FanSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]);
[WmiMethodId(34), Implemented, read, write, Description("Return Thermal Sensor Information")] void ThermalSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]);
};
Each WMI method takes an ACPI buffer containing a 32-bit index as input argument,
with the first 8 bit being used to specify the battery when using battery-related
WMI methods. Other WMI methods may ignore this argument or interpret it
differently. The WMI method output format varies:
* if the function has only a single output, then an ACPI object
of the corresponding type is returned
* if the function has multiple outputs, when an ACPI package
containing the outputs in the same order is returned
The format of the output should be thoroughly checked, since many methods can
return malformed data in case of an error.
The data format of many battery-related methods seems to be based on the
`Smart Battery Data Specification`, so unknown battery-related methods are
likely to follow this standard in some way.
WMI method GetBatteryDesignCapacity()
-------------------------------------
Returns the design capacity of the battery in mAh as an u16.
WMI method BatteryFullCharge()
------------------------------
Returns the full charge capacity of the battery in mAh as an u16.
WMI method BatteryManufactureName()
-----------------------------------
Returns the manufacture name of the battery as an ASCII string.
WMI method BatteryManufactureDate()
-----------------------------------
Returns the manufacture date of the battery as an u16.
The date is encoded in the following manner:
- bits 0 to 4 contain the manufacture day.
- bits 5 to 8 contain the manufacture month.
- bits 9 to 15 contain the manufacture year biased by 1980.
.. note::
The data format needs to be verified on more machines.
WMI method BatterySerialNumber()
--------------------------------
Returns the serial number of the battery as an u16.
WMI method BatteryChemistryValue()
----------------------------------
Returns the chemistry of the battery as an ASCII string.
Known values are:
- "Li-I" for Li-Ion
WMI method BatteryTemperature()
-------------------------------
Returns the temperature of the battery in tenth degree kelvin as an u16.
WMI method BatteryCurrent()
---------------------------
Returns the current flow of the battery in mA as an s16.
Negative values indicate discharging.
WMI method BatteryVoltage()
---------------------------
Returns the voltage flow of the battery in mV as an u16.
WMI method BatteryManufactureAccess()
-------------------------------------
Returns a manufacture-defined value as an u16.
WMI method BatteryRelativeStateOfCharge()
-----------------------------------------
Returns the capacity of the battery in percent as an u16.
WMI method BatteryCycleCount()
------------------------------
Returns the cycle count of the battery as an u16.
WMI method BatteryePPID()
-------------------------
Returns the ePPID of the battery as an ASCII string.
WMI method BatteryeRawAnalyticsStart()
--------------------------------------
Performs an analysis of the battery and returns a status code:
- ``0x0``: Success
- ``0x1``: Interface not supported
- ``0xfffffffe``: Error/Timeout
.. note::
The meaning of this method is still largely unknown.
WMI method BatteryeRawAnalytics()
---------------------------------
Returns a buffer usually containg 12 blocks of analytics data.
Those blocks contain:
- block number starting with 0 (u8)
- 31 bytes of unknown data
.. note::
The meaning of this method is still largely unknown.
WMI method BatteryDesignVoltage()
---------------------------------
Returns the design voltage of the battery in mV as an u16.
WMI method BatteryeRawAnalyticsABlock()
---------------------------------------
Returns a single block of analytics data, with the second byte
of the index being used for selecting the block number.
*Supported since WMI interface version 3!*
.. note::
The meaning of this method is still largely unknown.
WMI method ReturnVersion()
--------------------------
Returns the WMI interface version as an u32.
WMI method FanSensorInformation()
---------------------------------
Returns a buffer containg fan sensor entries, terminated
with a single ``0xff``.
Those entries contain:
- fan type (u8)
- fan speed in RPM (little endian u16)
WMI method ThermalSensorInformation()
-------------------------------------
Returns a buffer containing thermal sensor entries, terminated
with a single ``0xff``.
Those entries contain:
- thermal type (u8)
- current temperature (s8)
- min. temperature (s8)
- max. temperature (s8)
- unknown field (u8)
.. note::
TODO: Find out what the meaning of the last byte is.
ACPI battery matching algorithm
===============================
The algorithm used to match ACPI batteries to indices is based on information
which was found inside the logging messages of the OEM software.
Basically for each new ACPI battery, the serial numbers of the batteries behind
indices 1 till 3 are compared with the serial number of the ACPI battery.
Since the serial number of the ACPI battery can either be encoded as a normal
integer or as a hexadecimal value, both cases need to be checked. The first
index with a matching serial number is then selected.
A serial number of 0 indicates that the corresponding index is not associated
with an actual battery, or that the associated battery is not present.
Some machines like the Dell Inspiron 3505 only support a single battery and thus
ignore the battery index. Because of this the driver depends on the ACPI battery
hook mechanism to discover batteries.
.. note::
The ACPI battery matching algorithm currently used inside the driver is
outdated and does not match the algorithm described above. The reasons for
this are differences in the handling of the ToHexString() ACPI opcode between
Linux and Windows, which distorts the serial number of ACPI batteries on many
machines. Until this issue is resolved, the driver cannot use the above
algorithm.
Reverse-Engineering the DDV WMI interface
=========================================
1. Find a supported Dell notebook, usually made after ~2020.
2. Dump the ACPI tables and search for the WMI device (usually called "ADDV").
3. Decode the corresponding bmof data and look at the ASL code.
4. Try to deduce the meaning of a certain WMI method by comparing the control
flow with other ACPI methods (_BIX or _BIF for battery related methods
for example).
5. Use the built-in UEFI diagostics to view sensor types/values for fan/thermal
related methods (sometimes overwriting static ACPI data fields can be used
to test different sensor type values, since on some machines this data is
not reinitialized upon a warm reset).
Alternatively:
1. Load the ``dell-wmi-ddv`` driver, use the ``force`` module param
if necessary.
2. Use the debugfs interface to access the raw fan/thermal sensor buffer data.
3. Compare the data with the built-in UEFI diagnostics.
In case the DDV WMI interface version available on your Dell notebook is not
supported or you are seeing unknown fan/thermal sensors, please submit a
bugreport on `bugzilla <https://bugzilla.kernel.org>`_ so they can be added
to the ``dell-wmi-ddv`` driver.
See Documentation/admin-guide/reporting-issues.rst for further information.

View File

@@ -0,0 +1,22 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
=============================
Driver-specific Documentation
=============================
This section provides information about various devices supported by
the Linux kernel, their protocols and driver details.
.. toctree::
:maxdepth: 1
:numbered:
:glob:
*
.. only:: subproject and html
Indices
=======
* :ref:`genindex`

View File

@@ -0,0 +1,25 @@
.. SPDX-License-Identifier: GPL-2.0-only
==============================
WMI embedded Binary MOF driver
==============================
Introduction
============
Many machines embed WMI Binary MOF (Managed Object Format) metadata used to
describe the details of their ACPI WMI interfaces. The data can be decoded
with tools like `bmfdec <https://github.com/pali/bmfdec>`_ to obtain a
human readable WMI interface description, which is useful for developing
new WMI drivers.
The Binary MOF data can be retrieved from the ``bmof`` sysfs attribute of the
associated WMI device. Please note that multiple WMI devices containing Binary
MOF data can exist on a given system.
WMI interface
=============
The Binary MOF WMI device is identified by the WMI GUID ``05901221-D566-11D1-B2F0-00A0C9062910``.
The Binary MOF can be obtained by doing a WMI data block query. The result is
then returned as an ACPI buffer with a variable size.

View File

@@ -0,0 +1,19 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
=============
WMI Subsystem
=============
.. toctree::
:maxdepth: 1
acpi-interface
devices/index
.. only:: subproject and html
Indices
=======
* :ref:`genindex`

View File

@@ -456,6 +456,8 @@ F: include/linux/acpi_viot.h
ACPI WMI DRIVER
L: platform-driver-x86@vger.kernel.org
S: Orphan
F: Documentation/driver-api/wmi.rst
F: Documentation/wmi/
F: drivers/platform/x86/wmi.c
F: include/uapi/linux/wmi.h
@@ -5842,6 +5844,7 @@ M: Armin Wolf <W_Armin@gmx.de>
S: Maintained
F: Documentation/ABI/testing/debugfs-dell-wmi-ddv
F: Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv
F: Documentation/wmi/devices/dell-wmi-ddv.rst
F: drivers/platform/x86/dell/dell-wmi-ddv.c
DELL WMI DESCRIPTOR DRIVER
@@ -22910,6 +22913,13 @@ L: linux-wireless@vger.kernel.org
S: Odd fixes
F: drivers/net/wireless/legacy/wl3501*
WMI BINARY MOF DRIVER
L: platform-drivers-x86@vger.kernel.org
S: Orphan
F: Documentation/ABI/stable/sysfs-platform-wmi-bmof
F: Documentation/wmi/devices/wmi-bmof.rst
F: drivers/platform/x86/wmi-bmof.c
WOLFSON MICROELECTRONICS DRIVERS
L: patches@opensource.cirrus.com
S: Supported

View File

@@ -11,6 +11,7 @@
#include <linux/acpi.h>
#include <linux/arm-smccc.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -45,10 +46,39 @@ static const char * const mlxbf_bootctl_lifecycle_states[] = {
[3] = "RMA",
};
/* Log header format. */
#define MLXBF_RSH_LOG_TYPE_MASK GENMASK_ULL(59, 56)
#define MLXBF_RSH_LOG_LEN_MASK GENMASK_ULL(54, 48)
#define MLXBF_RSH_LOG_LEVEL_MASK GENMASK_ULL(7, 0)
/* Log module ID and type (only MSG type in Linux driver for now). */
#define MLXBF_RSH_LOG_TYPE_MSG 0x04ULL
/* Log ctl/data register offset. */
#define MLXBF_RSH_SCRATCH_BUF_CTL_OFF 0
#define MLXBF_RSH_SCRATCH_BUF_DATA_OFF 0x10
/* Log message levels. */
enum {
MLXBF_RSH_LOG_INFO,
MLXBF_RSH_LOG_WARN,
MLXBF_RSH_LOG_ERR,
MLXBF_RSH_LOG_ASSERT
};
/* Mapped pointer for RSH_BOOT_FIFO_DATA and RSH_BOOT_FIFO_COUNT register. */
static void __iomem *mlxbf_rsh_boot_data;
static void __iomem *mlxbf_rsh_boot_cnt;
/* Mapped pointer for rsh log semaphore/ctrl/data register. */
static void __iomem *mlxbf_rsh_semaphore;
static void __iomem *mlxbf_rsh_scratch_buf_ctl;
static void __iomem *mlxbf_rsh_scratch_buf_data;
/* Rsh log levels. */
static const char * const mlxbf_rsh_log_level[] = {
"INFO", "WARN", "ERR", "ASSERT"};
/* ARM SMC call which is atomic and no need for lock. */
static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg)
{
@@ -266,12 +296,108 @@ static ssize_t fw_reset_store(struct device *dev,
return count;
}
/* Size(8-byte words) of the log buffer. */
#define RSH_SCRATCH_BUF_CTL_IDX_MASK 0x7f
/* 100ms timeout */
#define RSH_SCRATCH_BUF_POLL_TIMEOUT 100000
static int mlxbf_rsh_log_sem_lock(void)
{
unsigned long reg;
return readq_poll_timeout(mlxbf_rsh_semaphore, reg, !reg, 0,
RSH_SCRATCH_BUF_POLL_TIMEOUT);
}
static void mlxbf_rsh_log_sem_unlock(void)
{
writeq(0, mlxbf_rsh_semaphore);
}
static ssize_t rsh_log_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int rc, idx, num, len, level = MLXBF_RSH_LOG_INFO;
size_t size = count;
u64 data;
if (!size)
return -EINVAL;
if (!mlxbf_rsh_semaphore || !mlxbf_rsh_scratch_buf_ctl)
return -EOPNOTSUPP;
/* Ignore line break at the end. */
if (buf[size - 1] == '\n')
size--;
/* Check the message prefix. */
for (idx = 0; idx < ARRAY_SIZE(mlxbf_rsh_log_level); idx++) {
len = strlen(mlxbf_rsh_log_level[idx]);
if (len + 1 < size &&
!strncmp(buf, mlxbf_rsh_log_level[idx], len)) {
buf += len;
size -= len;
level = idx;
break;
}
}
/* Ignore leading spaces. */
while (size > 0 && buf[0] == ' ') {
size--;
buf++;
}
/* Take the semaphore. */
rc = mlxbf_rsh_log_sem_lock();
if (rc)
return rc;
/* Calculate how many words are available. */
idx = readq(mlxbf_rsh_scratch_buf_ctl);
num = min((int)DIV_ROUND_UP(size, sizeof(u64)),
RSH_SCRATCH_BUF_CTL_IDX_MASK - idx - 1);
if (num <= 0)
goto done;
/* Write Header. */
data = FIELD_PREP(MLXBF_RSH_LOG_TYPE_MASK, MLXBF_RSH_LOG_TYPE_MSG);
data |= FIELD_PREP(MLXBF_RSH_LOG_LEN_MASK, num);
data |= FIELD_PREP(MLXBF_RSH_LOG_LEVEL_MASK, level);
writeq(data, mlxbf_rsh_scratch_buf_data);
/* Write message. */
for (idx = 0; idx < num && size > 0; idx++) {
if (size < sizeof(u64)) {
data = 0;
memcpy(&data, buf, size);
size = 0;
} else {
memcpy(&data, buf, sizeof(u64));
size -= sizeof(u64);
buf += sizeof(u64);
}
writeq(data, mlxbf_rsh_scratch_buf_data);
}
done:
/* Release the semaphore. */
mlxbf_rsh_log_sem_unlock();
/* Ignore the rest if no more space. */
return count;
}
static DEVICE_ATTR_RW(post_reset_wdog);
static DEVICE_ATTR_RW(reset_action);
static DEVICE_ATTR_RW(second_reset_action);
static DEVICE_ATTR_RO(lifecycle_state);
static DEVICE_ATTR_RO(secure_boot_fuse_state);
static DEVICE_ATTR_WO(fw_reset);
static DEVICE_ATTR_WO(rsh_log);
static struct attribute *mlxbf_bootctl_attrs[] = {
&dev_attr_post_reset_wdog.attr,
@@ -280,6 +406,7 @@ static struct attribute *mlxbf_bootctl_attrs[] = {
&dev_attr_lifecycle_state.attr,
&dev_attr_secure_boot_fuse_state.attr,
&dev_attr_fw_reset.attr,
&dev_attr_rsh_log.attr,
NULL
};
@@ -345,19 +472,32 @@ static bool mlxbf_bootctl_guid_match(const guid_t *guid,
static int mlxbf_bootctl_probe(struct platform_device *pdev)
{
struct arm_smccc_res res = { 0 };
void __iomem *reg;
guid_t guid;
int ret;
/* Get the resource of the bootfifo data register. */
/* Map the resource of the bootfifo data register. */
mlxbf_rsh_boot_data = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mlxbf_rsh_boot_data))
return PTR_ERR(mlxbf_rsh_boot_data);
/* Get the resource of the bootfifo counter register. */
/* Map the resource of the bootfifo counter register. */
mlxbf_rsh_boot_cnt = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(mlxbf_rsh_boot_cnt))
return PTR_ERR(mlxbf_rsh_boot_cnt);
/* Map the resource of the rshim semaphore register. */
mlxbf_rsh_semaphore = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(mlxbf_rsh_semaphore))
return PTR_ERR(mlxbf_rsh_semaphore);
/* Map the resource of the scratch buffer (log) registers. */
reg = devm_platform_ioremap_resource(pdev, 3);
if (IS_ERR(reg))
return PTR_ERR(reg);
mlxbf_rsh_scratch_buf_ctl = reg + MLXBF_RSH_SCRATCH_BUF_CTL_OFF;
mlxbf_rsh_scratch_buf_data = reg + MLXBF_RSH_SCRATCH_BUF_DATA_OFF;
/* Ensure we have the UUID we expect for this service. */
arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res);
guid_parse(mlxbf_bootctl_svc_uuid_str, &guid);

View File

@@ -573,7 +573,7 @@ static const struct acpi_device_id mshw0011_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, mshw0011_acpi_match);
static struct i2c_driver mshw0011_driver = {
.probe_new = mshw0011_probe,
.probe = mshw0011_probe,
.remove = mshw0011_remove,
.driver = {
.name = "mshw0011",

View File

@@ -43,8 +43,8 @@ config WMI_BMOF
default ACPI_WMI
help
Say Y here if you want to be able to read a firmware-embedded
WMI Binary MOF data. Using this requires userspace tools and may be
rather tedious.
WMI Binary MOF (Managed Object Format) data. Using this requires
userspace tools and may be rather tedious.
To compile this driver as a module, choose M here: the module will
be called wmi-bmof.
@@ -121,10 +121,11 @@ config GIGABYTE_WMI
To compile this driver as a module, choose M here: the module will
be called gigabyte-wmi.
config YOGABOOK_WMI
tristate "Lenovo Yoga Book tablet WMI key driver"
config YOGABOOK
tristate "Lenovo Yoga Book tablet key driver"
depends on ACPI_WMI
depends on INPUT
depends on I2C
select LEDS_CLASS
select NEW_LEDS
help
@@ -132,7 +133,7 @@ config YOGABOOK_WMI
control on the Lenovo Yoga Book tablets.
To compile this driver as a module, choose M here: the module will
be called lenovo-yogabook-wmi.
be called lenovo-yogabook.
config ACERHDF
tristate "Acer Aspire One temperature and fan driver"

View File

@@ -14,7 +14,6 @@ obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
obj-$(CONFIG_YOGABOOK_WMI) += lenovo-yogabook-wmi.o
# Acer
obj-$(CONFIG_ACERHDF) += acerhdf.o
@@ -66,6 +65,7 @@ obj-$(CONFIG_LENOVO_YMC) += lenovo-ymc.o
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o
obj-$(CONFIG_YOGABOOK) += lenovo-yogabook.o
# Intel
obj-y += intel/

View File

@@ -45,7 +45,6 @@
#define AMD_PMC_STB_DUMMY_PC 0xC6000007
/* STB S2D(Spill to DRAM) has different message port offset */
#define STB_SPILL_TO_DRAM 0xBE
#define AMD_S2D_REGISTER_MESSAGE 0xA20
#define AMD_S2D_REGISTER_RESPONSE 0xA80
#define AMD_S2D_REGISTER_ARGUMENT 0xA88
@@ -99,7 +98,6 @@
#define PMC_MSG_DELAY_MIN_US 50
#define RESPONSE_REGISTER_LOOP_MAX 20000
#define SOC_SUBSYSTEM_IP_MAX 12
#define DELAY_MIN_US 2000
#define DELAY_MAX_US 3000
#define FIFO_SIZE 4096
@@ -115,6 +113,7 @@ enum s2d_arg {
S2D_PHYS_ADDR_LOW,
S2D_PHYS_ADDR_HIGH,
S2D_NUM_SAMPLES,
S2D_DRAM_SIZE,
};
struct amd_pmc_bit_map {
@@ -132,9 +131,18 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = {
{"ISP", BIT(6)},
{"NBIO", BIT(7)},
{"DF", BIT(8)},
{"USB0", BIT(9)},
{"USB1", BIT(10)},
{"USB3_0", BIT(9)},
{"USB3_1", BIT(10)},
{"LAPIC", BIT(11)},
{"USB3_2", BIT(12)},
{"USB3_3", BIT(13)},
{"USB3_4", BIT(14)},
{"USB4_0", BIT(15)},
{"USB4_1", BIT(16)},
{"MPM", BIT(17)},
{"JPEG", BIT(18)},
{"IPU", BIT(19)},
{"UMSCH", BIT(20)},
{}
};
@@ -147,6 +155,9 @@ struct amd_pmc_dev {
u32 base_addr;
u32 cpu_id;
u32 active_ips;
u32 dram_size;
u32 num_ips;
u32 s2d_msg_id;
/* SMU version information */
u8 smu_program;
u8 major;
@@ -194,8 +205,8 @@ struct smu_metrics {
u64 timein_s0i3_totaltime;
u64 timein_swdrips_lastcapture;
u64 timein_swdrips_totaltime;
u64 timecondition_notmet_lastcapture[SOC_SUBSYSTEM_IP_MAX];
u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX];
u64 timecondition_notmet_lastcapture[32];
u64 timecondition_notmet_totaltime[32];
} __packed;
static int amd_pmc_stb_debugfs_open(struct inode *inode, struct file *filp)
@@ -261,7 +272,7 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp)
dev->msg_port = 1;
/* Get the num_samples to calculate the last push location */
ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, STB_SPILL_TO_DRAM, 1);
ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, dev->s2d_msg_id, true);
/* Clear msg_port for other SMU operation */
dev->msg_port = 0;
if (ret) {
@@ -308,6 +319,23 @@ static const struct file_operations amd_pmc_stb_debugfs_fops_v2 = {
.release = amd_pmc_stb_debugfs_release_v2,
};
static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev)
{
switch (dev->cpu_id) {
case AMD_CPU_ID_PCO:
case AMD_CPU_ID_RN:
case AMD_CPU_ID_YC:
case AMD_CPU_ID_CB:
dev->num_ips = 12;
dev->s2d_msg_id = 0xBE;
break;
case AMD_CPU_ID_PS:
dev->num_ips = 21;
dev->s2d_msg_id = 0x85;
break;
}
}
static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
{
if (dev->cpu_id == AMD_CPU_ID_PCO) {
@@ -317,15 +345,15 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
/* Get Active devices list from SMU */
if (!dev->active_ips)
amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, 1);
amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, true);
/* Get dram address */
if (!dev->smu_virt_addr) {
u32 phys_addr_low, phys_addr_hi;
u64 smu_phys_addr;
amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, 1);
amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, 1);
amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, true);
amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, true);
smu_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
dev->smu_virt_addr = devm_ioremap(dev->dev, smu_phys_addr,
@@ -335,8 +363,8 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
}
/* Start the logging */
amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, 0);
amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, 0);
amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, false);
amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, false);
return 0;
}
@@ -377,7 +405,7 @@ static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev)
if (dev->cpu_id == AMD_CPU_ID_PCO)
return -ENODEV;
rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, 1);
rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, true);
if (rc)
return rc;
@@ -469,7 +497,7 @@ static int smu_fw_info_show(struct seq_file *s, void *unused)
table.timeto_resume_to_os_lastcapture);
seq_puts(s, "\n=== Active time (in us) ===\n");
for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) {
for (idx = 0 ; idx < dev->num_ips ; idx++) {
if (soc15_ip_blk[idx].bit_mask & dev->active_ips)
seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name,
table.timecondition_notmet_lastcapture[idx]);
@@ -562,6 +590,18 @@ static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
debugfs_remove_recursive(dev->dbgfs_dir);
}
static bool amd_pmc_is_stb_supported(struct amd_pmc_dev *dev)
{
switch (dev->cpu_id) {
case AMD_CPU_ID_YC:
case AMD_CPU_ID_CB:
case AMD_CPU_ID_PS:
return true;
default:
return false;
}
}
static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
{
dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL);
@@ -573,8 +613,7 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
&amd_pmc_idlemask_fops);
/* Enable STB only when the module_param is set */
if (enable_stb) {
if (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB ||
dev->cpu_id == AMD_CPU_ID_PS)
if (amd_pmc_is_stb_supported(dev))
debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
&amd_pmc_stb_debugfs_fops_v2);
else
@@ -794,7 +833,7 @@ static void amd_pmc_s2idle_prepare(void)
}
msg = amd_pmc_get_os_hint(pdev);
rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, 0);
rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, false);
if (rc) {
dev_err(pdev->dev, "suspend failed: %d\n", rc);
return;
@@ -829,7 +868,7 @@ static int amd_pmc_dump_data(struct amd_pmc_dev *pdev)
if (pdev->cpu_id == AMD_CPU_ID_PCO)
return -ENODEV;
return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0);
return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, false);
}
static void amd_pmc_s2idle_restore(void)
@@ -839,7 +878,7 @@ static void amd_pmc_s2idle_restore(void)
u8 msg;
msg = amd_pmc_get_os_hint(pdev);
rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0);
rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, false);
if (rc)
dev_err(pdev->dev, "resume failed: %d\n", rc);
@@ -890,29 +929,65 @@ static const struct pci_device_id pmc_pci_ids[] = {
{ }
};
static int amd_pmc_get_dram_size(struct amd_pmc_dev *dev)
{
int ret;
switch (dev->cpu_id) {
case AMD_CPU_ID_YC:
if (!(dev->major > 90 || (dev->major == 90 && dev->minor > 39))) {
ret = -EINVAL;
goto err_dram_size;
}
break;
default:
ret = -EINVAL;
goto err_dram_size;
}
ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
if (ret || !dev->dram_size)
goto err_dram_size;
return 0;
err_dram_size:
dev_err(dev->dev, "DRAM size command not supported for this platform\n");
return ret;
}
static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
{
u32 phys_addr_low, phys_addr_hi;
u64 stb_phys_addr;
u32 size = 0;
int ret;
/* Spill to DRAM feature uses separate SMU message port */
dev->msg_port = 1;
amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, STB_SPILL_TO_DRAM, 1);
/* Get num of IP blocks within the SoC */
amd_pmc_get_ip_info(dev);
amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->s2d_msg_id, true);
if (size != S2D_TELEMETRY_BYTES_MAX)
return -EIO;
/* Get DRAM size */
ret = amd_pmc_get_dram_size(dev);
if (ret)
dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX;
/* Get STB DRAM address */
amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, STB_SPILL_TO_DRAM, 1);
amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, STB_SPILL_TO_DRAM, 1);
amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, dev->s2d_msg_id, true);
amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, dev->s2d_msg_id, true);
stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
/* Clear msg_port for other SMU operation */
dev->msg_port = 0;
dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, S2D_TELEMETRY_DRAMBYTES_MAX);
dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size);
if (!dev->stb_virt_addr)
return -ENOMEM;
@@ -1001,7 +1076,7 @@ static int amd_pmc_probe(struct platform_device *pdev)
mutex_init(&dev->lock);
if (enable_stb && (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB)) {
if (enable_stb && amd_pmc_is_stb_supported(dev)) {
err = amd_pmc_s2d_init(dev);
if (err)
goto err_pci_dev_put;

Some files were not shown because too many files have changed in this diff Show More