mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
platform-drivers-x86 for v6.15-1
Highlights:
- alienware-wmi: Refactor and split WMAX/legacy drivers
- dell-ddv:
- Correct +0.1 offset in temperature
- Use the power supply extension mechanism for battery temperatures
- intel/pmc:
- Refactor init to mostly use a common init function
- Add support for Arrow Lake U/H
- Add support for Panther Lake
- intel/sst:
- Improve multi die handling
- Prefix header search path with sysroot (fixes cross-compiling)
- lenovo-wmi-hotkey-utilities: Support for mic & audio mute LEDs
- samsung-galaxybook: Add driver for Samsung Galaxy Book series
- wmi:
- Rework WCxx/WExx ACPI method handling
- Enable data block collection when the data block is set
- platform/arm:
- Add Huawei Matebook E Go EC driver
- platform/mellanox:
- Relocate to drivers/platform/mellanox/
- mlxbf-bootctl: RTC battery status sysfs support
- Miscellaneous cleanups / refactoring / improvements
The following is an automated shortlog grouped by driver:
alienware-wmi:
- Add a state container for LED control feature
- Add a state container for thermal control methods
- Add alienware-wmi.h
- Add WMI Drivers
- Refactor hdmi, amplifier, deepslp methods
- Refactor LED control methods
- Refactor thermal control methods
- Rename alienware-wmi.c
- Split DMI table
- Split the alienware-wmi driver
- Update alienware-wmi config entries
- Update header and module information
amd/pmc:
- fix leak in probe()
- Move macros and structures to the PMC header file
- Notify user when platform does not support s0ix transition
- Remove unnecessary line breaks
- Use managed APIs for mutex
amd/pmf:
- convert timeouts to secs_to_jiffies()
amd:
- Use *-y instead of *-objs in Makefiles
arm64:
- add Huawei Matebook E Go EC driver
arm64: dts: qcom: gaokun3:
- Add Embedded Controller node
compal-laptop:
- Do not include <linux/fb.h>
dell-ddv:
- Fix temperature calculation
- Use devm_battery_hook_register
- Use the power supply extension mechanism
dell: dell-wmi-sysman:
- Use *-y instead of *-objs in Makefile
dell:
- Modify Makefile alignment
- Use *-y instead of *-objs in Makefile
dell-uart-backlight:
- Make dell_uart_bl_serdev_driver static
dt-bindings: platform:
- Add Huawei Matebook E Go EC
hp-bioscfg:
- Replace deprecated strncpy() with strscpy()
- Use wmi_instance_count()
hp:
- Use *-y instead of *-objs in Makefile
hwmon:
- (hp-wmi-sensors) Use the WMI bus API when accessing sensors
ideapad-laptop:
- use dev_groups to register attribute groups
int3472:
- Call "func" "con_id" instead
intel/pmc:
- Add Arrow Lake U/H support to intel_pmc_core driver
- Add Panther Lake support to intel_pmc_core
- Create generic_core_init() for all platforms
- Make tgl_core_generic_init() static
- Move arch specific action to init function
- Remove duplicate enum
- Remove simple init functions
- Remove unnecessary declarations in header
- Remove unneeded extern keyword in header
intel:
- Use *-y instead of *-objs in Makefile
irqdomain: platform/x86:
- Switch to irq_domain_create_linear()
lenovo-wmi-hotkey-utilities.c:
- Support for mic and audio mute LEDs
lenovo-yoga-tab2-pro-1380-fastcharger:
- Make symbol static
MAINTAINERS:
- Add documentation reference for Mellanox platform
- Update ALIENWARE WMI DRIVER entry
mellanox:
- Relocate mlx-platform driver
mlxbf-bootctl:
- Support sysfs entries for RTC battery status
mlx-platform:
- Change register name
- Cosmetic changes
samsung-galaxybook:
- Add samsung-galaxybook driver
- Fix block_recording not supported logic
sonypi:
- Use str_on_off() helper in sonypi_display_info()
think-lmi:
- Use ACPI object when extracting strings
- Use WMI bus API when accessing BIOS settings
thinkpad_acpi:
- check the return value of devm_mutex_init()
- convert timeouts to secs_to_jiffies()
- Do not include <linux/fb.h>
- Move HWMON initialization to tpacpi_hwmon_pdriver's probe
- Move subdriver initialization to tpacpi_pdriver's probe.
tools/power/x86/intel-speed-select:
- Die ID for IO dies
- Fix the condition to check multi die system
- Prefix header search path with sysroot
- Prevent increasing MAX_DIE_PER_PACKAGE
- v1.22 release
wmi:
- Call WCxx methods when setting data blocks
- Rework WCxx/WExx ACPI method handling
- Update documentation regarding the GUID-based API
- Use devres to disable the WMI device
x86-android-tablets:
- Add select POWER_SUPPLY to Kconfig
Merges:
- Merge branch 'fixes' into for-next
- Merge branch 'intel-sst' of https://github.com/spandruvada/linux-kernel into review-ilpo-next
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCZ+QJyQAKCRBZrE9hU+XO
MUPYAP4sjtB8DKTIHgiQqado7PJZmdgpeJfAplitwKGe4BOcEQEA1mhuqMA5n6S+
jvbTtRF+jiKxis/5zAtAdChScM/pIgo=
=W+gy
-----END PGP SIGNATURE-----
Merge tag 'platform-drivers-x86-v6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform drivers updates from Ilpo Järvinen:
- alienware-wmi:
- Refactor and split WMAX/legacy drivers
- dell-ddv:
- Correct +0.1 offset in temperature
- Use the power supply extension mechanism for battery temperatures
- intel/pmc:
- Refactor init to mostly use a common init function
- Add support for Arrow Lake U/H
- Add support for Panther Lake
- intel/sst:
- Improve multi die handling
- Prefix header search path with sysroot (fixes cross-compiling)
- lenovo-wmi-hotkey-utilities:
- Support for mic & audio mute LEDs
- samsung-galaxybook:
- Add driver for Samsung Galaxy Book series
- wmi:
- Rework WCxx/WExx ACPI method handling
- Enable data block collection when the data block is set
- platform/arm:
- Add Huawei Matebook E Go EC driver
- platform/mellanox:
- Relocate to drivers/platform/mellanox/
- mlxbf-bootctl:
- RTC battery status sysfs support
- Miscellaneous cleanups / refactoring / improvements
* tag 'platform-drivers-x86-v6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (75 commits)
platform/x86: x86-android-tablets: Add select POWER_SUPPLY to Kconfig
platform/x86/amd/pmf: convert timeouts to secs_to_jiffies()
platform/x86: thinkpad_acpi: convert timeouts to secs_to_jiffies()
irqdomain: platform/x86: Switch to irq_domain_create_linear()
platform/x86/amd/pmc: fix leak in probe()
tools/power/x86/intel-speed-select: v1.22 release
tools/power/x86/intel-speed-select: Prefix header search path with sysroot
tools/power/x86/intel-speed-select: Die ID for IO dies
tools/power/x86/intel-speed-select: Fix the condition to check multi die system
tools/power/x86/intel-speed-select: Prevent increasing MAX_DIE_PER_PACKAGE
platform/x86/amd/pmc: Use managed APIs for mutex
platform/x86/amd/pmc: Remove unnecessary line breaks
platform/x86/amd/pmc: Move macros and structures to the PMC header file
platform/x86/amd/pmc: Notify user when platform does not support s0ix transition
platform/x86: dell-ddv: Use the power supply extension mechanism
platform/x86: dell-ddv: Use devm_battery_hook_register
platform/x86: dell-ddv: Fix temperature calculation
platform/x86: thinkpad_acpi: check the return value of devm_mutex_init()
platform/x86: samsung-galaxybook: Fix block_recording not supported logic
platform/x86: dell-uart-backlight: Make dell_uart_bl_serdev_driver static
...
This commit is contained in:
commit
fb1ceb29b2
|
|
@ -150,3 +150,13 @@ Description:
|
|||
The "mfg_lock" sysfs attribute is write-only.
|
||||
A successful write to this attribute will latch the
|
||||
board-level attributes into EEPROM, making them read-only.
|
||||
|
||||
What: /sys/bus/platform/devices/MLNXBF04:00/rtc_battery
|
||||
Date: June 2025
|
||||
KernelVersion: 6.15
|
||||
Contact: "Xiangrong Li <xiangrongl@nvidia.com>"
|
||||
Description:
|
||||
The "rtc_battery" sysfs attribute is read-only.
|
||||
A successful read from this attribute returns the status of
|
||||
the board's RTC battery. The RTC battery status register is
|
||||
also cleared upon successful read operation.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Laptop Drivers
|
|||
disk-shock-protection
|
||||
laptop-mode
|
||||
lg-laptop
|
||||
samsung-galaxybook
|
||||
sony-laptop
|
||||
sonypi
|
||||
thinkpad-acpi
|
||||
|
|
|
|||
174
Documentation/admin-guide/laptops/samsung-galaxybook.rst
Normal file
174
Documentation/admin-guide/laptops/samsung-galaxybook.rst
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
==========================
|
||||
Samsung Galaxy Book Driver
|
||||
==========================
|
||||
|
||||
Joshua Grisham <josh@joshuagrisham.com>
|
||||
|
||||
This is a Linux x86 platform driver for Samsung Galaxy Book series notebook
|
||||
devices which utilizes Samsung's ``SCAI`` ACPI device in order to control
|
||||
extra features and receive various notifications.
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
||||
Any device with one of the supported ACPI device IDs should be supported. This
|
||||
covers most of the "Samsung Galaxy Book" series notebooks that are currently
|
||||
available as of this writing, and could include other Samsung notebook devices
|
||||
as well.
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
The following features are currently supported:
|
||||
|
||||
- :ref:`Keyboard backlight <keyboard-backlight>` control
|
||||
- :ref:`Performance mode <performance-mode>` control implemented using the
|
||||
platform profile interface
|
||||
- :ref:`Battery charge control end threshold
|
||||
<battery-charge-control-end-threshold>` (stop charging battery at given
|
||||
percentage value) implemented as a battery hook
|
||||
- :ref:`Firmware Attributes <firmware-attributes>` to allow control of various
|
||||
device settings
|
||||
- :ref:`Handling of Fn hotkeys <keyboard-hotkey-actions>` for various actions
|
||||
- :ref:`Handling of ACPI notifications and hotkeys
|
||||
<acpi-notifications-and-hotkey-actions>`
|
||||
|
||||
Because different models of these devices can vary in their features, there is
|
||||
logic built within the driver which attempts to test each implemented feature
|
||||
for a valid response before enabling its support (registering additional devices
|
||||
or extensions, adding sysfs attributes, etc). Therefore, it can be important to
|
||||
note that not all features may be supported for your particular device.
|
||||
|
||||
The following features might be possible to implement but will require
|
||||
additional investigation and are therefore not supported at this time:
|
||||
|
||||
- "Dolby Atmos" mode for the speakers
|
||||
- "Outdoor Mode" for increasing screen brightness on models with ``SAM0427``
|
||||
- "Silent Mode" on models with ``SAM0427``
|
||||
|
||||
.. _keyboard-backlight:
|
||||
|
||||
Keyboard backlight
|
||||
==================
|
||||
|
||||
A new LED class named ``samsung-galaxybook::kbd_backlight`` is created which
|
||||
will then expose the device using the standard sysfs-based LED interface at
|
||||
``/sys/class/leds/samsung-galaxybook::kbd_backlight``. Brightness can be
|
||||
controlled by writing the desired value to the ``brightness`` sysfs attribute or
|
||||
with any other desired userspace utility.
|
||||
|
||||
.. note::
|
||||
Most of these devices have an ambient light sensor which also turns
|
||||
off the keyboard backlight under well-lit conditions. This behavior does not
|
||||
seem possible to control at this time, but can be good to be aware of.
|
||||
|
||||
.. _performance-mode:
|
||||
|
||||
Performance mode
|
||||
================
|
||||
|
||||
This driver implements the
|
||||
Documentation/userspace-api/sysfs-platform_profile.rst interface for working
|
||||
with the "performance mode" function of the Samsung ACPI device.
|
||||
|
||||
Mapping of each Samsung "performance mode" to its respective platform profile is
|
||||
performed dynamically by the driver, as not all models support all of the same
|
||||
performance modes. Your device might have one or more of the following mappings:
|
||||
|
||||
- "Silent" maps to ``low-power``
|
||||
- "Quiet" maps to ``quiet``
|
||||
- "Optimized" maps to ``balanced``
|
||||
- "High performance" maps to ``performance``
|
||||
|
||||
The result of the mapping can be printed in the kernel log when the module is
|
||||
loaded. Supported profiles can also be retrieved from
|
||||
``/sys/firmware/acpi/platform_profile_choices``, while
|
||||
``/sys/firmware/acpi/platform_profile`` can be used to read or write the
|
||||
currently selected profile.
|
||||
|
||||
The ``balanced`` platform profile will be set during module load if no profile
|
||||
has been previously set.
|
||||
|
||||
.. _battery-charge-control-end-threshold:
|
||||
|
||||
Battery charge control end threshold
|
||||
====================================
|
||||
|
||||
This platform driver will add the ability to set the battery's charge control
|
||||
end threshold, but does not have the ability to set a start threshold.
|
||||
|
||||
This feature is typically called "Battery Saver" by the various Samsung
|
||||
applications in Windows, but in Linux we have implemented the standardized
|
||||
"charge control threshold" sysfs interface on the battery device to allow for
|
||||
controlling this functionality from the userspace.
|
||||
|
||||
The sysfs attribute
|
||||
``/sys/class/power_supply/BAT1/charge_control_end_threshold`` can be used to
|
||||
read or set the desired charge end threshold.
|
||||
|
||||
If you wish to maintain interoperability with the Samsung Settings application
|
||||
in Windows, then you should set the value to 100 to represent "off", or enable
|
||||
the feature using only one of the following values: 50, 60, 70, 80, or 90.
|
||||
Otherwise, the driver will accept any value between 1 and 100 as the percentage
|
||||
that you wish the battery to stop charging at.
|
||||
|
||||
.. note::
|
||||
Some devices have been observed as automatically "turning off" the charge
|
||||
control end threshold if an input value of less than 30 is given.
|
||||
|
||||
.. _firmware-attributes:
|
||||
|
||||
Firmware Attributes
|
||||
===================
|
||||
|
||||
The following enumeration-typed firmware attributes are set up by this driver
|
||||
and should be accessible under
|
||||
``/sys/class/firmware-attributes/samsung-galaxybook/attributes/`` if your device
|
||||
supports them:
|
||||
|
||||
- ``power_on_lid_open`` (device should power on when the lid is opened)
|
||||
- ``usb_charging`` (USB ports can deliver power to connected devices even when
|
||||
the device is powered off or in a low sleep state)
|
||||
- ``block_recording`` (blocks access to camera and microphone)
|
||||
|
||||
All of these attributes are simple boolean-like enumeration values which use 0
|
||||
to represent "off" and 1 to represent "on". Use the ``current_value`` attribute
|
||||
to get or change the setting on the device.
|
||||
|
||||
Note that when ``block_recording`` is updated, the input device "Samsung Galaxy
|
||||
Book Lens Cover" will receive a ``SW_CAMERA_LENS_COVER`` switch event which
|
||||
reflects the current state.
|
||||
|
||||
.. _keyboard-hotkey-actions:
|
||||
|
||||
Keyboard hotkey actions (i8042 filter)
|
||||
======================================
|
||||
|
||||
The i8042 filter will swallow the keyboard events for the Fn+F9 hotkey (Multi-
|
||||
level keyboard backlight toggle) and Fn+F10 hotkey (Block recording toggle)
|
||||
and instead execute their actions within the driver itself.
|
||||
|
||||
Fn+F9 will cycle through the brightness levels of the keyboard backlight. A
|
||||
notification will be sent using ``led_classdev_notify_brightness_hw_changed``
|
||||
so that the userspace can be aware of the change. This mimics the behavior of
|
||||
other existing devices where the brightness level is cycled internally by the
|
||||
embedded controller and then reported via a notification.
|
||||
|
||||
Fn+F10 will toggle the value of the "block recording" setting, which blocks
|
||||
or allows usage of the built-in camera and microphone (and generates the same
|
||||
Lens Cover switch event mentioned above).
|
||||
|
||||
.. _acpi-notifications-and-hotkey-actions:
|
||||
|
||||
ACPI notifications and hotkey actions
|
||||
=====================================
|
||||
|
||||
ACPI notifications will generate ACPI netlink events under the device class
|
||||
``samsung-galaxybook`` and bus ID matching the Samsung ACPI device ID found on
|
||||
your device. The events can be received using userspace tools such as
|
||||
``acpi_listen`` and ``acpid``.
|
||||
|
||||
The Fn+F11 Performance mode hotkey will be handled by the driver; each keypress
|
||||
will cycle to the next available platform profile.
|
||||
124
Documentation/devicetree/bindings/platform/huawei,gaokun-ec.yaml
Normal file
124
Documentation/devicetree/bindings/platform/huawei,gaokun-ec.yaml
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/platform/huawei,gaokun-ec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Huawei Matebook E Go Embedded Controller
|
||||
|
||||
maintainers:
|
||||
- Pengyu Luo <mitltlatltl@gmail.com>
|
||||
|
||||
description:
|
||||
Different from other Qualcomm Snapdragon sc8180x and sc8280xp-based
|
||||
machines, the Huawei Matebook E Go tablets use embedded controllers
|
||||
while others use a system called PMIC GLink which handles battery,
|
||||
UCSI, USB Type-C DP Alt Mode. In addition, Huawei's implementation
|
||||
also handles additional features, such as charging thresholds, FN
|
||||
lock, smart charging, tablet lid status, thermal sensors, and more.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- huawei,gaokun3-ec
|
||||
|
||||
reg:
|
||||
const: 0x38
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
'^connector@[01]$':
|
||||
$ref: /schemas/connector/usb-connector.yaml#
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
embedded-controller@38 {
|
||||
compatible = "huawei,gaokun3-ec";
|
||||
reg = <0x38>;
|
||||
|
||||
interrupts-extended = <&tlmm 107 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
connector@0 {
|
||||
compatible = "usb-c-connector";
|
||||
reg = <0>;
|
||||
power-role = "dual";
|
||||
data-role = "dual";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
ucsi0_ss_in: endpoint {
|
||||
remote-endpoint = <&usb_0_qmpphy_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
ucsi0_sbu: endpoint {
|
||||
remote-endpoint = <&usb0_sbu_mux>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
connector@1 {
|
||||
compatible = "usb-c-connector";
|
||||
reg = <1>;
|
||||
power-role = "dual";
|
||||
data-role = "dual";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
ucsi1_ss_in: endpoint {
|
||||
remote-endpoint = <&usb_1_qmpphy_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
ucsi1_sbu: endpoint {
|
||||
remote-endpoint = <&usb1_sbu_mux>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -89,6 +89,9 @@ 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.
|
||||
|
||||
Those ACPI methods are also called before setting data blocks to match the
|
||||
behaviour of the Windows driver.
|
||||
|
||||
_WED ACPI method
|
||||
----------------
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@ on a given machine.
|
|||
Because of this, WMI drivers should use the state container design pattern as described in
|
||||
Documentation/driver-api/driver-model/design-patterns.rst.
|
||||
|
||||
.. warning:: Using both GUID-based and non-GUID-based functions for querying WMI data blocks and
|
||||
handling WMI events simultaneously on the same device is guaranteed to corrupt the
|
||||
WMI device state and might lead to erratic behaviour.
|
||||
|
||||
WMI method drivers
|
||||
------------------
|
||||
|
||||
|
|
|
|||
31
MAINTAINERS
31
MAINTAINERS
|
|
@ -793,10 +793,12 @@ F: Documentation/admin-guide/perf/alibaba_pmu.rst
|
|||
F: drivers/perf/alibaba_uncore_drw_pmu.c
|
||||
|
||||
ALIENWARE WMI DRIVER
|
||||
M: Kurt Borja <kuurtb@gmail.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
L: Dell.Client.Kernel@dell.com
|
||||
S: Maintained
|
||||
F: Documentation/wmi/devices/alienware-wmi.rst
|
||||
F: drivers/platform/x86/dell/alienware-wmi.c
|
||||
F: drivers/platform/x86/dell/alienware-wmi*
|
||||
|
||||
ALLEGRO DVT VIDEO IP CORE DRIVER
|
||||
M: Michael Tretter <m.tretter@pengutronix.de>
|
||||
|
|
@ -10750,6 +10752,13 @@ S: Maintained
|
|||
F: Documentation/networking/device_drivers/ethernet/huawei/hinic.rst
|
||||
F: drivers/net/ethernet/huawei/hinic/
|
||||
|
||||
HUAWEI MATEBOOK E GO EMBEDDED CONTROLLER DRIVER
|
||||
M: Pengyu Luo <mitltlatltl@gmail.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/platform/huawei,gaokun-ec.yaml
|
||||
F: drivers/platform/arm64/huawei-gaokun-ec.c
|
||||
F: include/linux/platform_data/huawei-gaokun-ec.h
|
||||
|
||||
HUGETLB SUBSYSTEM
|
||||
M: Muchun Song <muchun.song@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
|
|
@ -13213,6 +13222,12 @@ S: Maintained
|
|||
W: http://legousb.sourceforge.net/
|
||||
F: drivers/usb/misc/legousbtower.c
|
||||
|
||||
LENOVO WMI HOTKEY UTILITIES DRIVER
|
||||
M: Jackie Dong <xy-jackie@139.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/platform/x86/lenovo-wmi-hotkey-utilities.c
|
||||
|
||||
LETSKETCH HID TABLET DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
|
|
@ -15091,6 +15106,7 @@ M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
|
|||
M: Vadim Pasternak <vadimp@nvidia.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/ABI/stable/sysfs-driver-mlxreg-io
|
||||
F: Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
|
||||
F: drivers/platform/mellanox/
|
||||
F: include/linux/platform_data/mlxreg.h
|
||||
|
|
@ -15161,12 +15177,6 @@ F: Documentation/leds/leds-mlxcpld.rst
|
|||
F: drivers/leds/leds-mlxcpld.c
|
||||
F: drivers/leds/leds-mlxreg.c
|
||||
|
||||
MELLANOX PLATFORM DRIVER
|
||||
M: Vadim Pasternak <vadimp@nvidia.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/platform/x86/mlx-platform.c
|
||||
|
||||
MEMBARRIER SUPPORT
|
||||
M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
M: "Paul E. McKenney" <paulmck@kernel.org>
|
||||
|
|
@ -21094,6 +21104,13 @@ L: linux-fbdev@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/video/fbdev/s3c-fb.c
|
||||
|
||||
SAMSUNG GALAXY BOOK DRIVER
|
||||
M: Joshua Grisham <josh@joshuagrisham.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/admin-guide/laptops/samsung-galaxybook.rst
|
||||
F: drivers/platform/x86/samsung-galaxybook.c
|
||||
|
||||
SAMSUNG INTERCONNECT DRIVERS
|
||||
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
M: Artur Świgoń <a.swigon@samsung.com>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ / {
|
|||
|
||||
aliases {
|
||||
i2c4 = &i2c4;
|
||||
i2c15 = &i2c15;
|
||||
serial1 = &uart2;
|
||||
};
|
||||
|
||||
|
|
@ -216,6 +217,40 @@ map1 {
|
|||
};
|
||||
};
|
||||
|
||||
usb0-sbu-mux {
|
||||
compatible = "pericom,pi3usb102", "gpio-sbu-mux";
|
||||
|
||||
select-gpios = <&tlmm 164 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
pinctrl-0 = <&usb0_sbu_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
orientation-switch;
|
||||
|
||||
port {
|
||||
usb0_sbu_mux: endpoint {
|
||||
remote-endpoint = <&ucsi0_sbu>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
usb1-sbu-mux {
|
||||
compatible = "pericom,pi3usb102", "gpio-sbu-mux";
|
||||
|
||||
select-gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
pinctrl-0 = <&usb1_sbu_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
orientation-switch;
|
||||
|
||||
port {
|
||||
usb1_sbu_mux: endpoint {
|
||||
remote-endpoint = <&ucsi1_sbu>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
wcn6855-pmu {
|
||||
compatible = "qcom,wcn6855-pmu";
|
||||
|
||||
|
|
@ -584,6 +619,97 @@ touchscreen@4f {
|
|||
|
||||
};
|
||||
|
||||
&i2c15 {
|
||||
clock-frequency = <400000>;
|
||||
|
||||
pinctrl-0 = <&i2c15_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
status = "okay";
|
||||
|
||||
embedded-controller@38 {
|
||||
compatible = "huawei,gaokun3-ec";
|
||||
reg = <0x38>;
|
||||
|
||||
interrupts-extended = <&tlmm 107 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
connector@0 {
|
||||
compatible = "usb-c-connector";
|
||||
reg = <0>;
|
||||
power-role = "dual";
|
||||
data-role = "dual";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
ucsi0_hs_in: endpoint {
|
||||
remote-endpoint = <&usb_0_dwc3_hs>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
ucsi0_ss_in: endpoint {
|
||||
remote-endpoint = <&usb_0_qmpphy_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
|
||||
ucsi0_sbu: endpoint {
|
||||
remote-endpoint = <&usb0_sbu_mux>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
connector@1 {
|
||||
compatible = "usb-c-connector";
|
||||
reg = <1>;
|
||||
power-role = "dual";
|
||||
data-role = "dual";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
ucsi1_hs_in: endpoint {
|
||||
remote-endpoint = <&usb_1_dwc3_hs>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
ucsi1_ss_in: endpoint {
|
||||
remote-endpoint = <&usb_1_qmpphy_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
|
||||
ucsi1_sbu: endpoint {
|
||||
remote-endpoint = <&usb1_sbu_mux>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mdss0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
@ -1004,6 +1130,10 @@ &usb_0_dwc3 {
|
|||
dr_mode = "host";
|
||||
};
|
||||
|
||||
&usb_0_dwc3_hs {
|
||||
remote-endpoint = <&ucsi0_hs_in>;
|
||||
};
|
||||
|
||||
&usb_0_hsphy {
|
||||
vdda-pll-supply = <&vreg_l9d>;
|
||||
vdda18-supply = <&vreg_l1c>;
|
||||
|
|
@ -1025,6 +1155,10 @@ &usb_0_qmpphy_dp_in {
|
|||
remote-endpoint = <&mdss0_dp0_out>;
|
||||
};
|
||||
|
||||
&usb_0_qmpphy_out {
|
||||
remote-endpoint = <&ucsi0_ss_in>;
|
||||
};
|
||||
|
||||
&usb_1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
@ -1033,6 +1167,10 @@ &usb_1_dwc3 {
|
|||
dr_mode = "host";
|
||||
};
|
||||
|
||||
&usb_1_dwc3_hs {
|
||||
remote-endpoint = <&ucsi1_hs_in>;
|
||||
};
|
||||
|
||||
&usb_1_hsphy {
|
||||
vdda-pll-supply = <&vreg_l4b>;
|
||||
vdda18-supply = <&vreg_l1c>;
|
||||
|
|
@ -1054,6 +1192,10 @@ &usb_1_qmpphy_dp_in {
|
|||
remote-endpoint = <&mdss0_dp1_out>;
|
||||
};
|
||||
|
||||
&usb_1_qmpphy_out {
|
||||
remote-endpoint = <&ucsi1_ss_in>;
|
||||
};
|
||||
|
||||
&usb_2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
@ -1177,6 +1319,13 @@ i2c4_default: i2c4-default-state {
|
|||
bias-disable;
|
||||
};
|
||||
|
||||
i2c15_default: i2c15-default-state {
|
||||
pins = "gpio36", "gpio37";
|
||||
function = "qup15";
|
||||
drive-strength = <2>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mode_pin_active: mode-pin-state {
|
||||
pins = "gpio26";
|
||||
function = "gpio";
|
||||
|
|
@ -1301,6 +1450,20 @@ tx-pins {
|
|||
};
|
||||
};
|
||||
|
||||
usb0_sbu_default: usb0-sbu-state {
|
||||
pins = "gpio164";
|
||||
function = "gpio";
|
||||
drive-strength = <16>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
usb1_sbu_default: usb1-sbu-state {
|
||||
pins = "gpio47";
|
||||
function = "gpio";
|
||||
drive-strength = <16>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
wcd_default: wcd-default-state {
|
||||
reset-pins {
|
||||
pins = "gpio106";
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/kfifo.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
|
|
@ -1268,12 +1269,12 @@ static void sonypi_display_info(void)
|
|||
"compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
|
||||
sonypi_device.model,
|
||||
verbose,
|
||||
fnkeyinit ? "on" : "off",
|
||||
camera ? "on" : "off",
|
||||
compat ? "on" : "off",
|
||||
str_on_off(fnkeyinit),
|
||||
str_on_off(camera),
|
||||
str_on_off(compat),
|
||||
mask,
|
||||
useinput ? "on" : "off",
|
||||
SONYPI_ACPI_ACTIVE ? "on" : "off");
|
||||
str_on_off(useinput),
|
||||
str_on_off(SONYPI_ACPI_ACTIVE));
|
||||
printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
|
||||
sonypi_device.irq,
|
||||
sonypi_device.ioport1, sonypi_device.ioport2);
|
||||
|
|
|
|||
|
|
@ -1197,7 +1197,7 @@ static int hp_wmi_update_info(struct hp_wmi_sensors *state,
|
|||
if (time_after(jiffies, info->last_updated + HZ)) {
|
||||
mutex_lock(&state->lock);
|
||||
|
||||
wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, instance);
|
||||
wobj = wmidev_block_query(state->wdev, instance);
|
||||
if (!wobj) {
|
||||
ret = -EIO;
|
||||
goto out_unlock;
|
||||
|
|
@ -1745,7 +1745,7 @@ static int init_numeric_sensors(struct hp_wmi_sensors *state,
|
|||
return -ENOMEM;
|
||||
|
||||
for (i = 0, info = info_arr; i < icount; i++, info++) {
|
||||
wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, i);
|
||||
wobj = wmidev_block_query(state->wdev, i);
|
||||
if (!wobj)
|
||||
return -EIO;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,27 @@ config EC_ACER_ASPIRE1
|
|||
laptop where this information is not properly exposed via the
|
||||
standard ACPI devices.
|
||||
|
||||
config EC_HUAWEI_GAOKUN
|
||||
tristate "Huawei Matebook E Go Embedded Controller driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on I2C
|
||||
depends on INPUT
|
||||
depends on HWMON
|
||||
select AUXILIARY_BUS
|
||||
|
||||
help
|
||||
Say Y here to enable the EC driver for the Huawei Matebook E Go
|
||||
which is a sc8280xp-based 2-in-1 tablet. The driver handles battery
|
||||
(information, charge control) and USB Type-C DP HPD events as well
|
||||
as some misc functions like the lid sensor and temperature sensors,
|
||||
etc.
|
||||
|
||||
This driver provides battery and AC status support for the mentioned
|
||||
laptop where this information is not properly exposed via the
|
||||
standard ACPI devices.
|
||||
|
||||
Say M or Y here to include this support.
|
||||
|
||||
config EC_LENOVO_YOGA_C630
|
||||
tristate "Lenovo Yoga C630 Embedded Controller driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_EC_ACER_ASPIRE1) += acer-aspire1-ec.o
|
||||
obj-$(CONFIG_EC_HUAWEI_GAOKUN) += huawei-gaokun-ec.o
|
||||
obj-$(CONFIG_EC_LENOVO_YOGA_C630) += lenovo-yoga-c630.o
|
||||
|
|
|
|||
825
drivers/platform/arm64/huawei-gaokun-ec.c
Normal file
825
drivers/platform/arm64/huawei-gaokun-ec.c
Normal file
|
|
@ -0,0 +1,825 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* huawei-gaokun-ec - An EC driver for HUAWEI Matebook E Go
|
||||
*
|
||||
* Copyright (C) 2024-2025 Pengyu Luo <mitltlatltl@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_data/huawei-gaokun-ec.h>
|
||||
|
||||
#define EC_EVENT 0x06
|
||||
|
||||
/* Also can be found in ACPI specification 12.3 */
|
||||
#define EC_READ 0x80
|
||||
#define EC_WRITE 0x81
|
||||
#define EC_BURST 0x82
|
||||
#define EC_QUERY 0x84
|
||||
|
||||
#define EC_FN_LOCK_ON 0x5A
|
||||
#define EC_FN_LOCK_OFF 0x55
|
||||
#define EC_FN_LOCK_READ 0x6B
|
||||
#define EC_FN_LOCK_WRITE 0x6C
|
||||
|
||||
#define EC_EVENT_LID 0x81
|
||||
|
||||
#define EC_LID_STATE 0x80
|
||||
#define EC_LID_OPEN BIT(1)
|
||||
|
||||
#define EC_TEMP_REG 0x61
|
||||
|
||||
#define EC_STANDBY_REG 0xB2
|
||||
#define EC_STANDBY_ENTER 0xDB
|
||||
#define EC_STANDBY_EXIT 0xEB
|
||||
|
||||
enum gaokun_ec_smart_charge_cmd {
|
||||
SMART_CHARGE_DATA_WRITE = 0xE3,
|
||||
SMART_CHARGE_DATA_READ,
|
||||
SMART_CHARGE_ENABLE_WRITE,
|
||||
SMART_CHARGE_ENABLE_READ,
|
||||
};
|
||||
|
||||
enum gaokun_ec_ucsi_cmd {
|
||||
UCSI_REG_WRITE = 0xD2,
|
||||
UCSI_REG_READ,
|
||||
UCSI_DATA_WRITE,
|
||||
UCSI_DATA_READ,
|
||||
};
|
||||
|
||||
#define UCSI_REG_SIZE 7
|
||||
|
||||
/*
|
||||
* For tx, command sequences are arranged as
|
||||
* {master_cmd, slave_cmd, data_len, data_seq}
|
||||
*/
|
||||
#define REQ_HDR_SIZE 3
|
||||
#define INPUT_SIZE_OFFSET 2
|
||||
#define REQ_LEN(req) (REQ_HDR_SIZE + (req)[INPUT_SIZE_OFFSET])
|
||||
|
||||
/*
|
||||
* For rx, data sequences are arranged as
|
||||
* {status, data_len(unreliable), data_seq}
|
||||
*/
|
||||
#define RESP_HDR_SIZE 2
|
||||
|
||||
#define MKREQ(REG0, REG1, SIZE, ...) \
|
||||
{ \
|
||||
REG0, REG1, SIZE, \
|
||||
/* ## will remove comma when SIZE is 0 */ \
|
||||
## __VA_ARGS__, \
|
||||
/* make sure len(pkt[3:]) >= SIZE */ \
|
||||
[3 + (SIZE)] = 0, \
|
||||
}
|
||||
|
||||
#define MKRESP(SIZE) \
|
||||
{ \
|
||||
[RESP_HDR_SIZE + (SIZE) - 1] = 0, \
|
||||
}
|
||||
|
||||
/* Possible size 1, 4, 20, 24. Most of the time, the size is 1. */
|
||||
static inline void refill_req(u8 *dest, const u8 *src, size_t size)
|
||||
{
|
||||
memcpy(dest + REQ_HDR_SIZE, src, size);
|
||||
}
|
||||
|
||||
static inline void refill_req_byte(u8 *dest, const u8 *src)
|
||||
{
|
||||
dest[REQ_HDR_SIZE] = *src;
|
||||
}
|
||||
|
||||
/* Possible size 1, 2, 4, 7, 20. Most of the time, the size is 1. */
|
||||
static inline void extr_resp(u8 *dest, const u8 *src, size_t size)
|
||||
{
|
||||
memcpy(dest, src + RESP_HDR_SIZE, size);
|
||||
}
|
||||
|
||||
static inline void extr_resp_byte(u8 *dest, const u8 *src)
|
||||
{
|
||||
*dest = src[RESP_HDR_SIZE];
|
||||
}
|
||||
|
||||
static inline void *extr_resp_shallow(const u8 *src)
|
||||
{
|
||||
return (void *)(src + RESP_HDR_SIZE);
|
||||
}
|
||||
|
||||
struct gaokun_ec {
|
||||
struct i2c_client *client;
|
||||
struct mutex lock; /* EC transaction lock */
|
||||
struct blocking_notifier_head notifier_list;
|
||||
struct device *hwmon_dev;
|
||||
struct input_dev *idev;
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
static int gaokun_ec_request(struct gaokun_ec *ec, const u8 *req,
|
||||
size_t resp_len, u8 *resp)
|
||||
{
|
||||
struct i2c_client *client = ec->client;
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = client->flags,
|
||||
.len = REQ_LEN(req),
|
||||
.buf = (void *)req,
|
||||
}, {
|
||||
.addr = client->addr,
|
||||
.flags = client->flags | I2C_M_RD,
|
||||
.len = resp_len,
|
||||
.buf = resp,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&ec->lock);
|
||||
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret != ARRAY_SIZE(msgs)) {
|
||||
dev_err(&client->dev, "I2C transfer error %d\n", ret);
|
||||
goto out_after_break;
|
||||
}
|
||||
|
||||
ret = *resp;
|
||||
if (ret)
|
||||
dev_err(&client->dev, "EC transaction error %d\n", ret);
|
||||
|
||||
out_after_break:
|
||||
usleep_range(2000, 2500); /* have a break, ACPI did this */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Common API */
|
||||
|
||||
/**
|
||||
* gaokun_ec_read - Read from EC
|
||||
* @ec: The gaokun_ec structure
|
||||
* @req: The sequence to request
|
||||
* @resp_len: The size to read
|
||||
* @resp: The buffer to store response sequence
|
||||
*
|
||||
* This function is used to read data after writing a magic sequence to EC.
|
||||
* All EC operations depend on this function.
|
||||
*
|
||||
* Huawei uses magic sequences everywhere to complete various functions, all
|
||||
* these sequences are passed to ECCD(a ACPI method which is quiet similar
|
||||
* to gaokun_ec_request), there is no good abstraction to generalize these
|
||||
* sequences, so just wrap it for now. Almost all magic sequences are kept
|
||||
* in this file.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_read(struct gaokun_ec *ec, const u8 *req,
|
||||
size_t resp_len, u8 *resp)
|
||||
{
|
||||
return gaokun_ec_request(ec, req, resp_len, resp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_read);
|
||||
|
||||
/**
|
||||
* gaokun_ec_write - Write to EC
|
||||
* @ec: The gaokun_ec structure
|
||||
* @req: The sequence to request
|
||||
*
|
||||
* This function has no big difference from gaokun_ec_read. When caller care
|
||||
* only write status and no actual data are returned, then use it.
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_write(struct gaokun_ec *ec, const u8 *req)
|
||||
{
|
||||
u8 ec_resp[] = MKRESP(0);
|
||||
|
||||
return gaokun_ec_request(ec, req, sizeof(ec_resp), ec_resp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_write);
|
||||
|
||||
int gaokun_ec_read_byte(struct gaokun_ec *ec, const u8 *req, u8 *byte)
|
||||
{
|
||||
int ret;
|
||||
u8 ec_resp[] = MKRESP(sizeof(*byte));
|
||||
|
||||
ret = gaokun_ec_read(ec, req, sizeof(ec_resp), ec_resp);
|
||||
extr_resp_byte(byte, ec_resp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_read_byte);
|
||||
|
||||
/**
|
||||
* gaokun_ec_register_notify - Register a notifier callback for EC events.
|
||||
* @ec: The gaokun_ec structure
|
||||
* @nb: Notifier block pointer to register
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_register_notify(struct gaokun_ec *ec, struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&ec->notifier_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_register_notify);
|
||||
|
||||
/**
|
||||
* gaokun_ec_unregister_notify - Unregister notifier callback for EC events.
|
||||
* @ec: The gaokun_ec structure
|
||||
* @nb: Notifier block pointer to unregister
|
||||
*
|
||||
* Unregister a notifier callback that was previously registered with
|
||||
* gaokun_ec_register_notify().
|
||||
*/
|
||||
void gaokun_ec_unregister_notify(struct gaokun_ec *ec, struct notifier_block *nb)
|
||||
{
|
||||
blocking_notifier_chain_unregister(&ec->notifier_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_unregister_notify);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* API for PSY */
|
||||
|
||||
/**
|
||||
* gaokun_ec_psy_multi_read - Read contiguous registers
|
||||
* @ec: The gaokun_ec structure
|
||||
* @reg: The start register
|
||||
* @resp_len: The number of registers to be read
|
||||
* @resp: The buffer to store response sequence
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_psy_multi_read(struct gaokun_ec *ec, u8 reg,
|
||||
size_t resp_len, u8 *resp)
|
||||
{
|
||||
u8 ec_req[] = MKREQ(0x02, EC_READ, 1, 0);
|
||||
u8 ec_resp[] = MKRESP(1);
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < resp_len; ++i, reg++) {
|
||||
refill_req_byte(ec_req, ®);
|
||||
ret = gaokun_ec_read(ec, ec_req, sizeof(ec_resp), ec_resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
extr_resp_byte(&resp[i], ec_resp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_psy_multi_read);
|
||||
|
||||
/* Smart charge */
|
||||
|
||||
/**
|
||||
* gaokun_ec_psy_get_smart_charge - Get smart charge data from EC
|
||||
* @ec: The gaokun_ec structure
|
||||
* @resp: The buffer to store response sequence (mode, delay, start, end)
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_psy_get_smart_charge(struct gaokun_ec *ec,
|
||||
u8 resp[GAOKUN_SMART_CHARGE_DATA_SIZE])
|
||||
{
|
||||
/* GBCM */
|
||||
u8 ec_req[] = MKREQ(0x02, SMART_CHARGE_DATA_READ, 0);
|
||||
u8 ec_resp[] = MKRESP(GAOKUN_SMART_CHARGE_DATA_SIZE);
|
||||
int ret;
|
||||
|
||||
ret = gaokun_ec_read(ec, ec_req, sizeof(ec_resp), ec_resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
extr_resp(resp, ec_resp, GAOKUN_SMART_CHARGE_DATA_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_psy_get_smart_charge);
|
||||
|
||||
static inline bool validate_battery_threshold_range(u8 start, u8 end)
|
||||
{
|
||||
return end != 0 && start <= end && end <= 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* gaokun_ec_psy_set_smart_charge - Set smart charge data
|
||||
* @ec: The gaokun_ec structure
|
||||
* @req: The sequence to request (mode, delay, start, end)
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_psy_set_smart_charge(struct gaokun_ec *ec,
|
||||
const u8 req[GAOKUN_SMART_CHARGE_DATA_SIZE])
|
||||
{
|
||||
/* SBCM */
|
||||
u8 ec_req[] = MKREQ(0x02, SMART_CHARGE_DATA_WRITE,
|
||||
GAOKUN_SMART_CHARGE_DATA_SIZE);
|
||||
|
||||
if (!validate_battery_threshold_range(req[2], req[3]))
|
||||
return -EINVAL;
|
||||
|
||||
refill_req(ec_req, req, GAOKUN_SMART_CHARGE_DATA_SIZE);
|
||||
|
||||
return gaokun_ec_write(ec, ec_req);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_psy_set_smart_charge);
|
||||
|
||||
/* Smart charge enable */
|
||||
|
||||
/**
|
||||
* gaokun_ec_psy_get_smart_charge_enable - Get smart charge state
|
||||
* @ec: The gaokun_ec structure
|
||||
* @on: The state
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_psy_get_smart_charge_enable(struct gaokun_ec *ec, bool *on)
|
||||
{
|
||||
/* GBAC */
|
||||
u8 ec_req[] = MKREQ(0x02, SMART_CHARGE_ENABLE_READ, 0);
|
||||
u8 state;
|
||||
int ret;
|
||||
|
||||
ret = gaokun_ec_read_byte(ec, ec_req, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*on = !!state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_psy_get_smart_charge_enable);
|
||||
|
||||
/**
|
||||
* gaokun_ec_psy_set_smart_charge_enable - Set smart charge state
|
||||
* @ec: The gaokun_ec structure
|
||||
* @on: The state
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_psy_set_smart_charge_enable(struct gaokun_ec *ec, bool on)
|
||||
{
|
||||
/* SBAC */
|
||||
u8 ec_req[] = MKREQ(0x02, SMART_CHARGE_ENABLE_WRITE, 1, on);
|
||||
|
||||
return gaokun_ec_write(ec, ec_req);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_psy_set_smart_charge_enable);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* API for UCSI */
|
||||
|
||||
/**
|
||||
* gaokun_ec_ucsi_read - Read UCSI data from EC
|
||||
* @ec: The gaokun_ec structure
|
||||
* @resp: The buffer to store response sequence
|
||||
*
|
||||
* Read CCI and MSGI (used by UCSI subdriver).
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_ucsi_read(struct gaokun_ec *ec,
|
||||
u8 resp[GAOKUN_UCSI_READ_SIZE])
|
||||
{
|
||||
u8 ec_req[] = MKREQ(0x03, UCSI_DATA_READ, 0);
|
||||
u8 ec_resp[] = MKRESP(GAOKUN_UCSI_READ_SIZE);
|
||||
int ret;
|
||||
|
||||
ret = gaokun_ec_read(ec, ec_req, sizeof(ec_resp), ec_resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
extr_resp(resp, ec_resp, GAOKUN_UCSI_READ_SIZE);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_ucsi_read);
|
||||
|
||||
/**
|
||||
* gaokun_ec_ucsi_write - Write UCSI data to EC
|
||||
* @ec: The gaokun_ec structure
|
||||
* @req: The sequence to request
|
||||
*
|
||||
* Write CTRL and MSGO (used by UCSI subdriver).
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_ucsi_write(struct gaokun_ec *ec,
|
||||
const u8 req[GAOKUN_UCSI_WRITE_SIZE])
|
||||
{
|
||||
u8 ec_req[] = MKREQ(0x03, UCSI_DATA_WRITE, GAOKUN_UCSI_WRITE_SIZE);
|
||||
|
||||
refill_req(ec_req, req, GAOKUN_UCSI_WRITE_SIZE);
|
||||
|
||||
return gaokun_ec_write(ec, ec_req);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_ucsi_write);
|
||||
|
||||
/**
|
||||
* gaokun_ec_ucsi_get_reg - Get UCSI register from EC
|
||||
* @ec: The gaokun_ec structure
|
||||
* @ureg: The gaokun ucsi register
|
||||
*
|
||||
* Get UCSI register data (used by UCSI subdriver).
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_ucsi_get_reg(struct gaokun_ec *ec, struct gaokun_ucsi_reg *ureg)
|
||||
{
|
||||
u8 ec_req[] = MKREQ(0x03, UCSI_REG_READ, 0);
|
||||
u8 ec_resp[] = MKRESP(UCSI_REG_SIZE);
|
||||
int ret;
|
||||
|
||||
ret = gaokun_ec_read(ec, ec_req, sizeof(ec_resp), ec_resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
extr_resp((u8 *)ureg, ec_resp, UCSI_REG_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_ucsi_get_reg);
|
||||
|
||||
/**
|
||||
* gaokun_ec_ucsi_pan_ack - Ack pin assignment notifications from EC
|
||||
* @ec: The gaokun_ec structure
|
||||
* @port_id: The port id receiving and handling the notifications
|
||||
*
|
||||
* Ack pin assignment notifications (used by UCSI subdriver).
|
||||
*
|
||||
* Return: 0 on success or negative error code.
|
||||
*/
|
||||
int gaokun_ec_ucsi_pan_ack(struct gaokun_ec *ec, int port_id)
|
||||
{
|
||||
u8 ec_req[] = MKREQ(0x03, UCSI_REG_WRITE, 1);
|
||||
u8 data = 1 << port_id;
|
||||
|
||||
if (port_id == GAOKUN_UCSI_NO_PORT_UPDATE)
|
||||
data = 0;
|
||||
|
||||
refill_req_byte(ec_req, &data);
|
||||
|
||||
return gaokun_ec_write(ec, ec_req);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gaokun_ec_ucsi_pan_ack);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* EC Sysfs */
|
||||
|
||||
/* Fn lock */
|
||||
static int gaokun_ec_get_fn_lock(struct gaokun_ec *ec, bool *on)
|
||||
{
|
||||
/* GFRS */
|
||||
u8 ec_req[] = MKREQ(0x02, EC_FN_LOCK_READ, 0);
|
||||
int ret;
|
||||
u8 state;
|
||||
|
||||
ret = gaokun_ec_read_byte(ec, ec_req, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (state == EC_FN_LOCK_ON)
|
||||
*on = true;
|
||||
else if (state == EC_FN_LOCK_OFF)
|
||||
*on = false;
|
||||
else
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gaokun_ec_set_fn_lock(struct gaokun_ec *ec, bool on)
|
||||
{
|
||||
/* SFRS */
|
||||
u8 ec_req[] = MKREQ(0x02, EC_FN_LOCK_WRITE, 1,
|
||||
on ? EC_FN_LOCK_ON : EC_FN_LOCK_OFF);
|
||||
|
||||
return gaokun_ec_write(ec, ec_req);
|
||||
}
|
||||
|
||||
static ssize_t fn_lock_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct gaokun_ec *ec = dev_get_drvdata(dev);
|
||||
bool on;
|
||||
int ret;
|
||||
|
||||
ret = gaokun_ec_get_fn_lock(ec, &on);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sysfs_emit(buf, "%d\n", on);
|
||||
}
|
||||
|
||||
static ssize_t fn_lock_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct gaokun_ec *ec = dev_get_drvdata(dev);
|
||||
bool on;
|
||||
int ret;
|
||||
|
||||
if (kstrtobool(buf, &on))
|
||||
return -EINVAL;
|
||||
|
||||
ret = gaokun_ec_set_fn_lock(ec, on);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(fn_lock);
|
||||
|
||||
static struct attribute *gaokun_ec_attrs[] = {
|
||||
&dev_attr_fn_lock.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(gaokun_ec);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Thermal Zone HwMon */
|
||||
|
||||
/* Range from 0 to 0x2C, partially valid */
|
||||
static const u8 temp_reg[] = {
|
||||
0x05, 0x07, 0x08, 0x0E, 0x0F, 0x12, 0x15, 0x1E,
|
||||
0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
|
||||
0x27, 0x28, 0x29, 0x2A
|
||||
};
|
||||
|
||||
static int gaokun_ec_get_temp(struct gaokun_ec *ec, u8 idx, long *temp)
|
||||
{
|
||||
/* GTMP */
|
||||
u8 ec_req[] = MKREQ(0x02, EC_TEMP_REG, 1, temp_reg[idx]);
|
||||
u8 ec_resp[] = MKRESP(sizeof(__le16));
|
||||
__le16 *tmp;
|
||||
int ret;
|
||||
|
||||
ret = gaokun_ec_read(ec, ec_req, sizeof(ec_resp), ec_resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tmp = (__le16 *)extr_resp_shallow(ec_resp);
|
||||
*temp = le16_to_cpu(*tmp) * 100; /* convert to HwMon's unit */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static umode_t
|
||||
gaokun_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
return type == hwmon_temp ? 0444 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gaokun_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
struct gaokun_ec *ec = dev_get_drvdata(dev);
|
||||
|
||||
if (type == hwmon_temp)
|
||||
return gaokun_ec_get_temp(ec, channel, val);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct hwmon_ops gaokun_ec_hwmon_ops = {
|
||||
.is_visible = gaokun_ec_hwmon_is_visible,
|
||||
.read = gaokun_ec_hwmon_read,
|
||||
};
|
||||
|
||||
static u32 gaokun_ec_temp_config[] = {
|
||||
[0 ... ARRAY_SIZE(temp_reg) - 1] = HWMON_T_INPUT,
|
||||
0
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info gaokun_ec_temp = {
|
||||
.type = hwmon_temp,
|
||||
.config = gaokun_ec_temp_config,
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info * const gaokun_ec_hwmon_info[] = {
|
||||
&gaokun_ec_temp,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info gaokun_ec_hwmon_chip_info = {
|
||||
.ops = &gaokun_ec_hwmon_ops,
|
||||
.info = gaokun_ec_hwmon_info,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Modern Standby */
|
||||
|
||||
static int gaokun_ec_suspend(struct device *dev)
|
||||
{
|
||||
struct gaokun_ec *ec = dev_get_drvdata(dev);
|
||||
u8 ec_req[] = MKREQ(0x02, EC_STANDBY_REG, 1, EC_STANDBY_ENTER);
|
||||
int ret;
|
||||
|
||||
if (ec->suspended)
|
||||
return 0;
|
||||
|
||||
ret = gaokun_ec_write(ec, ec_req);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ec->suspended = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gaokun_ec_resume(struct device *dev)
|
||||
{
|
||||
struct gaokun_ec *ec = dev_get_drvdata(dev);
|
||||
u8 ec_req[] = MKREQ(0x02, EC_STANDBY_REG, 1, EC_STANDBY_EXIT);
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (!ec->suspended)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
ret = gaokun_ec_write(ec, ec_req);
|
||||
if (ret == 0)
|
||||
break;
|
||||
|
||||
msleep(100); /* EC need time to resume */
|
||||
};
|
||||
|
||||
ec->suspended = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gaokun_aux_release(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *adev = to_auxiliary_dev(dev);
|
||||
|
||||
kfree(adev);
|
||||
}
|
||||
|
||||
static void gaokun_aux_remove(void *data)
|
||||
{
|
||||
struct auxiliary_device *adev = data;
|
||||
|
||||
auxiliary_device_delete(adev);
|
||||
auxiliary_device_uninit(adev);
|
||||
}
|
||||
|
||||
static int gaokun_aux_init(struct device *parent, const char *name,
|
||||
struct gaokun_ec *ec)
|
||||
{
|
||||
struct auxiliary_device *adev;
|
||||
int ret;
|
||||
|
||||
adev = kzalloc(sizeof(*adev), GFP_KERNEL);
|
||||
if (!adev)
|
||||
return -ENOMEM;
|
||||
|
||||
adev->name = name;
|
||||
adev->id = 0;
|
||||
adev->dev.parent = parent;
|
||||
adev->dev.release = gaokun_aux_release;
|
||||
adev->dev.platform_data = ec;
|
||||
/* Allow aux devices to access parent's DT nodes directly */
|
||||
device_set_of_node_from_dev(&adev->dev, parent);
|
||||
|
||||
ret = auxiliary_device_init(adev);
|
||||
if (ret) {
|
||||
kfree(adev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = auxiliary_device_add(adev);
|
||||
if (ret) {
|
||||
auxiliary_device_uninit(adev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return devm_add_action_or_reset(parent, gaokun_aux_remove, adev);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* EC */
|
||||
|
||||
static irqreturn_t gaokun_ec_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct gaokun_ec *ec = data;
|
||||
u8 ec_req[] = MKREQ(EC_EVENT, EC_QUERY, 0);
|
||||
u8 status, id;
|
||||
int ret;
|
||||
|
||||
ret = gaokun_ec_read_byte(ec, ec_req, &id);
|
||||
if (ret)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
switch (id) {
|
||||
case 0x0: /* No event */
|
||||
break;
|
||||
|
||||
case EC_EVENT_LID:
|
||||
gaokun_ec_psy_read_byte(ec, EC_LID_STATE, &status);
|
||||
status &= EC_LID_OPEN;
|
||||
input_report_switch(ec->idev, SW_LID, !status);
|
||||
input_sync(ec->idev);
|
||||
break;
|
||||
|
||||
default:
|
||||
blocking_notifier_call_chain(&ec->notifier_list, id, ec);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int gaokun_ec_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct gaokun_ec *ec;
|
||||
int ret;
|
||||
|
||||
ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
|
||||
if (!ec)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_mutex_init(dev, &ec->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ec->client = client;
|
||||
i2c_set_clientdata(client, ec);
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&ec->notifier_list);
|
||||
|
||||
/* Lid switch */
|
||||
ec->idev = devm_input_allocate_device(dev);
|
||||
if (!ec->idev)
|
||||
return -ENOMEM;
|
||||
|
||||
ec->idev->name = "LID";
|
||||
ec->idev->phys = "gaokun-ec/input0";
|
||||
input_set_capability(ec->idev, EV_SW, SW_LID);
|
||||
|
||||
ret = input_register_device(ec->idev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to register input device\n");
|
||||
|
||||
ret = gaokun_aux_init(dev, GAOKUN_DEV_PSY, ec);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = gaokun_aux_init(dev, GAOKUN_DEV_UCSI, ec);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, client->irq, NULL,
|
||||
gaokun_ec_irq_handler, IRQF_ONESHOT,
|
||||
dev_name(dev), ec);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to request IRQ\n");
|
||||
|
||||
ec->hwmon_dev = devm_hwmon_device_register_with_info(dev, "gaokun_ec_hwmon",
|
||||
ec, &gaokun_ec_hwmon_chip_info, NULL);
|
||||
if (IS_ERR(ec->hwmon_dev))
|
||||
return dev_err_probe(dev, PTR_ERR(ec->hwmon_dev),
|
||||
"Failed to register hwmon device\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id gaokun_ec_id[] = {
|
||||
{ "gaokun-ec", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, gaokun_ec_id);
|
||||
|
||||
static const struct of_device_id gaokun_ec_of_match[] = {
|
||||
{ .compatible = "huawei,gaokun3-ec", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, gaokun_ec_of_match);
|
||||
|
||||
static const struct dev_pm_ops gaokun_ec_pm_ops = {
|
||||
NOIRQ_SYSTEM_SLEEP_PM_OPS(gaokun_ec_suspend, gaokun_ec_resume)
|
||||
};
|
||||
|
||||
static struct i2c_driver gaokun_ec_driver = {
|
||||
.driver = {
|
||||
.name = "gaokun-ec",
|
||||
.of_match_table = gaokun_ec_of_match,
|
||||
.pm = &gaokun_ec_pm_ops,
|
||||
.dev_groups = gaokun_ec_groups,
|
||||
},
|
||||
.probe = gaokun_ec_probe,
|
||||
.id_table = gaokun_ec_id,
|
||||
};
|
||||
module_i2c_driver(gaokun_ec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("HUAWEI Matebook E Go EC driver");
|
||||
MODULE_AUTHOR("Pengyu Luo <mitltlatltl@gmail.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -14,6 +14,19 @@ menuconfig MELLANOX_PLATFORM
|
|||
|
||||
if MELLANOX_PLATFORM
|
||||
|
||||
config MLX_PLATFORM
|
||||
tristate "Mellanox Technologies platform support"
|
||||
depends on ACPI && I2C && PCI
|
||||
select REGMAP
|
||||
help
|
||||
This option enables system support for the Mellanox Technologies
|
||||
platform. The Mellanox systems provide data center networking
|
||||
solutions based on Virtual Protocol Interconnect (VPI) technology
|
||||
enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE
|
||||
connection.
|
||||
|
||||
If you have a Mellanox system, say Y or M here.
|
||||
|
||||
config MLXREG_HOTPLUG
|
||||
tristate "Mellanox platform hotplug driver support"
|
||||
depends on HWMON
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
# Makefile for linux/drivers/platform/mellanox
|
||||
# Mellanox Platform-Specific Drivers
|
||||
#
|
||||
obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
|
||||
obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o
|
||||
obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o
|
||||
obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@
|
|||
#define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET 0xd9
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD6_MVER_OFFSET 0xd9
|
||||
#define MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET 0xdb
|
||||
#define MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET 0xda
|
||||
#define MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET 0xdc
|
||||
|
|
@ -2247,7 +2247,7 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_modular_data = {
|
|||
.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
|
||||
};
|
||||
|
||||
/* Platform hotplug for NVLink blade systems family data */
|
||||
/* Platform hotplug for NVLink blade systems family data */
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_global_wp_items_data[] = {
|
||||
{
|
||||
.label = "global_wp_grant",
|
||||
|
|
@ -2279,7 +2279,7 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_chassis_blade_data = {
|
|||
.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
|
||||
};
|
||||
|
||||
/* Platform hotplug for switch systems family data */
|
||||
/* Platform hotplug for switch systems family data */
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_erot_ap_items_data[] = {
|
||||
{
|
||||
.label = "erot1_ap",
|
||||
|
|
@ -2387,7 +2387,7 @@ static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_l1_switch_pwr_events_
|
|||
.user_handler = mlxplat_mlxcpld_l1_switch_pwr_events_handler,
|
||||
};
|
||||
|
||||
/* Platform hotplug for l1 switch systems family data */
|
||||
/* Platform hotplug for l1 switch systems family data */
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_pwr_events_items_data[] = {
|
||||
{
|
||||
.label = "power_button",
|
||||
|
|
@ -4401,7 +4401,7 @@ static struct mlxreg_core_platform_data mlxplat_modular_regs_io_data = {
|
|||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_modular_regs_io_data),
|
||||
};
|
||||
|
||||
/* Platform register access for chassis blade systems family data */
|
||||
/* Platform register access for chassis blade systems family data */
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_chassis_blade_regs_io_data[] = {
|
||||
{
|
||||
.label = "cpld1_version",
|
||||
|
|
@ -5050,7 +5050,6 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
|||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET:
|
||||
|
|
@ -5186,7 +5185,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
|||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD6_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET:
|
||||
|
|
@ -5343,7 +5342,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
|||
case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD6_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET:
|
||||
|
|
@ -6573,7 +6572,7 @@ static int mlxplat_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Set default registers. */
|
||||
for (i = 0; i < mlxplat_regmap_config->num_reg_defaults; i++) {
|
||||
for (i = 0; i < mlxplat_regmap_config->num_reg_defaults; i++) {
|
||||
err = regmap_write(priv->regmap,
|
||||
mlxplat_regmap_config->reg_defaults[i].reg,
|
||||
mlxplat_regmap_config->reg_defaults[i].def);
|
||||
|
|
@ -91,6 +91,7 @@ static const char * const mlxbf_rsh_log_level[] = {
|
|||
static DEFINE_MUTEX(icm_ops_lock);
|
||||
static DEFINE_MUTEX(os_up_lock);
|
||||
static DEFINE_MUTEX(mfg_ops_lock);
|
||||
static DEFINE_MUTEX(rtc_ops_lock);
|
||||
|
||||
/*
|
||||
* Objects are stored within the MFG partition per type.
|
||||
|
|
@ -489,6 +490,23 @@ static ssize_t large_icm_store(struct device *dev,
|
|||
return res.a0 ? -EPERM : count;
|
||||
}
|
||||
|
||||
static ssize_t rtc_battery_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
mutex_lock(&rtc_ops_lock);
|
||||
arm_smccc_smc(MLNX_HANDLE_GET_RTC_LOW_BATT, 0, 0, 0, 0,
|
||||
0, 0, 0, &res);
|
||||
mutex_unlock(&rtc_ops_lock);
|
||||
|
||||
if (res.a0)
|
||||
return -EPERM;
|
||||
|
||||
return sysfs_emit(buf, "0x%lx\n", res.a1);
|
||||
}
|
||||
|
||||
static ssize_t os_up_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
|
@ -906,6 +924,7 @@ static DEVICE_ATTR_RW(sn);
|
|||
static DEVICE_ATTR_RW(uuid);
|
||||
static DEVICE_ATTR_RW(rev);
|
||||
static DEVICE_ATTR_WO(mfg_lock);
|
||||
static DEVICE_ATTR_RO(rtc_battery);
|
||||
|
||||
static struct attribute *mlxbf_bootctl_attrs[] = {
|
||||
&dev_attr_post_reset_wdog.attr,
|
||||
|
|
@ -925,6 +944,7 @@ static struct attribute *mlxbf_bootctl_attrs[] = {
|
|||
&dev_attr_uuid.attr,
|
||||
&dev_attr_rev.attr,
|
||||
&dev_attr_mfg_lock.attr,
|
||||
&dev_attr_rtc_battery.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@
|
|||
*/
|
||||
#define MLNX_HANDLE_OS_UP 0x82000014
|
||||
|
||||
/*
|
||||
* SMC function ID to get and clear the RTC low voltage bit
|
||||
*/
|
||||
#define MLNX_HANDLE_GET_RTC_LOW_BATT 0x82000023
|
||||
|
||||
/* SMC function IDs for SiP Service queries */
|
||||
#define MLXBF_BOOTCTL_SIP_SVC_CALL_COUNT 0x8200ff00
|
||||
#define MLXBF_BOOTCTL_SIP_SVC_UID 0x8200ff01
|
||||
|
|
|
|||
|
|
@ -475,6 +475,17 @@ config IDEAPAD_LAPTOP
|
|||
This is a driver for Lenovo IdeaPad netbooks contains drivers for
|
||||
rfkill switch, hotkey, fan control and backlight control.
|
||||
|
||||
config LENOVO_WMI_HOTKEY_UTILITIES
|
||||
tristate "Lenovo Hotkey Utility WMI extras driver"
|
||||
depends on ACPI_WMI
|
||||
select NEW_LEDS
|
||||
select LEDS_CLASS
|
||||
imply IDEAPAD_LAPTOP
|
||||
help
|
||||
This driver provides WMI support for Lenovo customized hotkeys function,
|
||||
such as LED control for audio/mic mute event for Ideapad, YOGA, XiaoXin,
|
||||
Gaming, ThinkBook and so on.
|
||||
|
||||
config LENOVO_YMC
|
||||
tristate "Lenovo Yoga Tablet Mode Control"
|
||||
depends on ACPI_WMI
|
||||
|
|
@ -778,6 +789,23 @@ config BARCO_P50_GPIO
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called barco-p50-gpio.
|
||||
|
||||
config SAMSUNG_GALAXYBOOK
|
||||
tristate "Samsung Galaxy Book driver"
|
||||
depends on ACPI
|
||||
depends on ACPI_BATTERY
|
||||
depends on INPUT
|
||||
depends on LEDS_CLASS
|
||||
depends on SERIO_I8042
|
||||
select ACPI_PLATFORM_PROFILE
|
||||
select FW_ATTR_CLASS
|
||||
help
|
||||
This is a driver for Samsung Galaxy Book series notebooks. It adds
|
||||
support for the keyboard backlight control, performance mode control,
|
||||
function keys, and various firmware attributes.
|
||||
|
||||
For more information about this driver, see
|
||||
<file:Documentation/admin-guide/laptops/samsung-galaxybook.rst>.
|
||||
|
||||
config SAMSUNG_LAPTOP
|
||||
tristate "Samsung Laptop driver"
|
||||
depends on RFKILL || RFKILL = n
|
||||
|
|
@ -1012,19 +1040,6 @@ config SERIAL_MULTI_INSTANTIATE
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called serial-multi-instantiate.
|
||||
|
||||
config MLX_PLATFORM
|
||||
tristate "Mellanox Technologies platform support"
|
||||
depends on ACPI && I2C && PCI
|
||||
select REGMAP
|
||||
help
|
||||
This option enables system support for the Mellanox Technologies
|
||||
platform. The Mellanox systems provide data center networking
|
||||
solutions based on Virtual Protocol Interconnect (VPI) technology
|
||||
enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE
|
||||
connection.
|
||||
|
||||
If you have a Mellanox system, say Y or M here.
|
||||
|
||||
config TOUCHSCREEN_DMI
|
||||
bool "DMI based touchscreen configuration info"
|
||||
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ obj-$(CONFIG_UV_SYSFS) += uv_sysfs.o
|
|||
# IBM Thinkpad and Lenovo
|
||||
obj-$(CONFIG_IBM_RTL) += ibm_rtl.o
|
||||
obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o
|
||||
obj-$(CONFIG_LENOVO_WMI_HOTKEY_UTILITIES) += lenovo-wmi-hotkey-utilities.o
|
||||
obj-$(CONFIG_LENOVO_YMC) += lenovo-ymc.o
|
||||
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
|
||||
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
|
||||
|
|
@ -95,8 +96,9 @@ obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o
|
|||
obj-$(CONFIG_BARCO_P50_GPIO) += barco-p50-gpio.o
|
||||
|
||||
# Samsung
|
||||
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o
|
||||
obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
|
||||
obj-$(CONFIG_SAMSUNG_GALAXYBOOK) += samsung-galaxybook.o
|
||||
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o
|
||||
obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
|
||||
|
||||
# Toshiba
|
||||
obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
|
||||
|
|
@ -122,7 +124,6 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
|
|||
# Platform drivers
|
||||
obj-$(CONFIG_FW_ATTR_CLASS) += firmware_attributes_class.o
|
||||
obj-$(CONFIG_SERIAL_MULTI_INSTANTIATE) += serial-multi-instantiate.o
|
||||
obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o
|
||||
obj-$(CONFIG_WIRELESS_HOTKEY) += wireless-hotkey.o
|
||||
obj-$(CONFIG_X86_ANDROID_TABLETS) += x86-android-tablets/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_AMD_3D_VCACHE) += amd_3d_vcache.o
|
||||
amd_3d_vcache-objs := x3d_vcache.o
|
||||
amd_3d_vcache-y := x3d_vcache.o
|
||||
obj-$(CONFIG_AMD_PMC) += pmc/
|
||||
obj-$(CONFIG_AMD_HSMP) += hsmp/
|
||||
obj-$(CONFIG_AMD_PMF) += pmf/
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_AMD_HSMP) += hsmp_common.o
|
||||
hsmp_common-objs := hsmp.o
|
||||
hsmp_common-y := hsmp.o
|
||||
obj-$(CONFIG_AMD_HSMP_PLAT) += amd_hsmp.o
|
||||
amd_hsmp-objs := plat.o
|
||||
amd_hsmp-y := plat.o
|
||||
obj-$(CONFIG_AMD_HSMP_ACPI) += hsmp_acpi.o
|
||||
hsmp_acpi-objs := acpi.o
|
||||
hsmp_acpi-y := acpi.o
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
# AMD Power Management Controller Driver
|
||||
#
|
||||
|
||||
amd-pmc-objs := pmc.o pmc-quirks.o mp1_stb.o
|
||||
obj-$(CONFIG_AMD_PMC) += amd-pmc.o
|
||||
amd-pmc-$(CONFIG_AMD_MP2_STB) += mp2_stb.o
|
||||
obj-$(CONFIG_AMD_PMC) += amd-pmc.o
|
||||
amd-pmc-y := pmc.o pmc-quirks.o mp1_stb.o
|
||||
amd-pmc-$(CONFIG_AMD_MP2_STB) += mp2_stb.o
|
||||
|
|
|
|||
|
|
@ -32,70 +32,6 @@
|
|||
|
||||
#include "pmc.h"
|
||||
|
||||
/* SMU communication registers */
|
||||
#define AMD_PMC_REGISTER_RESPONSE 0x980
|
||||
#define AMD_PMC_REGISTER_ARGUMENT 0x9BC
|
||||
|
||||
/* PMC Scratch Registers */
|
||||
#define AMD_PMC_SCRATCH_REG_CZN 0x94
|
||||
#define AMD_PMC_SCRATCH_REG_YC 0xD14
|
||||
#define AMD_PMC_SCRATCH_REG_1AH 0xF14
|
||||
|
||||
/* STB Registers */
|
||||
#define AMD_PMC_STB_S2IDLE_PREPARE 0xC6000001
|
||||
#define AMD_PMC_STB_S2IDLE_RESTORE 0xC6000002
|
||||
#define AMD_PMC_STB_S2IDLE_CHECK 0xC6000003
|
||||
|
||||
/* Base address of SMU for mapping physical address to virtual address */
|
||||
#define AMD_PMC_MAPPING_SIZE 0x01000
|
||||
#define AMD_PMC_BASE_ADDR_OFFSET 0x10000
|
||||
#define AMD_PMC_BASE_ADDR_LO 0x13B102E8
|
||||
#define AMD_PMC_BASE_ADDR_HI 0x13B102EC
|
||||
#define AMD_PMC_BASE_ADDR_LO_MASK GENMASK(15, 0)
|
||||
#define AMD_PMC_BASE_ADDR_HI_MASK GENMASK(31, 20)
|
||||
|
||||
/* SMU Response Codes */
|
||||
#define AMD_PMC_RESULT_OK 0x01
|
||||
#define AMD_PMC_RESULT_CMD_REJECT_BUSY 0xFC
|
||||
#define AMD_PMC_RESULT_CMD_REJECT_PREREQ 0xFD
|
||||
#define AMD_PMC_RESULT_CMD_UNKNOWN 0xFE
|
||||
#define AMD_PMC_RESULT_FAILED 0xFF
|
||||
|
||||
/* FCH SSC Registers */
|
||||
#define FCH_S0I3_ENTRY_TIME_L_OFFSET 0x30
|
||||
#define FCH_S0I3_ENTRY_TIME_H_OFFSET 0x34
|
||||
#define FCH_S0I3_EXIT_TIME_L_OFFSET 0x38
|
||||
#define FCH_S0I3_EXIT_TIME_H_OFFSET 0x3C
|
||||
#define FCH_SSC_MAPPING_SIZE 0x800
|
||||
#define FCH_BASE_PHY_ADDR_LOW 0xFED81100
|
||||
#define FCH_BASE_PHY_ADDR_HIGH 0x00000000
|
||||
|
||||
/* SMU Message Definations */
|
||||
#define SMU_MSG_GETSMUVERSION 0x02
|
||||
#define SMU_MSG_LOG_GETDRAM_ADDR_HI 0x04
|
||||
#define SMU_MSG_LOG_GETDRAM_ADDR_LO 0x05
|
||||
#define SMU_MSG_LOG_START 0x06
|
||||
#define SMU_MSG_LOG_RESET 0x07
|
||||
#define SMU_MSG_LOG_DUMP_DATA 0x08
|
||||
#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09
|
||||
|
||||
#define PMC_MSG_DELAY_MIN_US 50
|
||||
#define RESPONSE_REGISTER_LOOP_MAX 20000
|
||||
|
||||
#define DELAY_MIN_US 2000
|
||||
#define DELAY_MAX_US 3000
|
||||
|
||||
enum amd_pmc_def {
|
||||
MSG_TEST = 0x01,
|
||||
MSG_OS_HINT_PCO,
|
||||
MSG_OS_HINT_RN,
|
||||
};
|
||||
|
||||
struct amd_pmc_bit_map {
|
||||
const char *name;
|
||||
u32 bit_mask;
|
||||
};
|
||||
|
||||
static const struct amd_pmc_bit_map soc15_ip_blk_v2[] = {
|
||||
{"DISPLAY", BIT(0)},
|
||||
{"CPU", BIT(1)},
|
||||
|
|
@ -165,23 +101,6 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3
|
|||
iowrite32(val, dev->regbase + reg_offset);
|
||||
}
|
||||
|
||||
struct smu_metrics {
|
||||
u32 table_version;
|
||||
u32 hint_count;
|
||||
u32 s0i3_last_entry_status;
|
||||
u32 timein_s0i2;
|
||||
u64 timeentering_s0i3_lastcapture;
|
||||
u64 timeentering_s0i3_totaltime;
|
||||
u64 timeto_resume_to_os_lastcapture;
|
||||
u64 timeto_resume_to_os_totaltime;
|
||||
u64 timein_s0i3_lastcapture;
|
||||
u64 timein_s0i3_totaltime;
|
||||
u64 timein_swdrips_lastcapture;
|
||||
u64 timein_swdrips_totaltime;
|
||||
u64 timecondition_notmet_lastcapture[32];
|
||||
u64 timecondition_notmet_totaltime[32];
|
||||
} __packed;
|
||||
|
||||
static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev)
|
||||
{
|
||||
switch (dev->cpu_id) {
|
||||
|
|
@ -247,11 +166,12 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
|
|||
|
||||
static int get_metrics_table(struct amd_pmc_dev *pdev, struct smu_metrics *table)
|
||||
{
|
||||
if (!pdev->smu_virt_addr) {
|
||||
int ret = amd_pmc_setup_smu_logging(pdev);
|
||||
int rc;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!pdev->smu_virt_addr) {
|
||||
rc = amd_pmc_setup_smu_logging(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (pdev->cpu_id == AMD_CPU_ID_PCO)
|
||||
|
|
@ -300,10 +220,10 @@ static ssize_t smu_fw_version_show(struct device *d, struct device_attribute *at
|
|||
char *buf)
|
||||
{
|
||||
struct amd_pmc_dev *dev = dev_get_drvdata(d);
|
||||
int rc;
|
||||
|
||||
if (!dev->major) {
|
||||
int rc = amd_pmc_get_smu_version(dev);
|
||||
|
||||
rc = amd_pmc_get_smu_version(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -314,10 +234,10 @@ static ssize_t smu_program_show(struct device *d, struct device_attribute *attr,
|
|||
char *buf)
|
||||
{
|
||||
struct amd_pmc_dev *dev = dev_get_drvdata(d);
|
||||
int rc;
|
||||
|
||||
if (!dev->major) {
|
||||
int rc = amd_pmc_get_smu_version(dev);
|
||||
|
||||
rc = amd_pmc_get_smu_version(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -778,14 +698,14 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = {
|
|||
static int amd_pmc_suspend_handler(struct device *dev)
|
||||
{
|
||||
struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Must be called only from the same set of dev_pm_ops handlers
|
||||
* as i8042_pm_suspend() is called: currently just from .suspend.
|
||||
*/
|
||||
if (pdev->disable_8042_wakeup && !disable_workarounds) {
|
||||
int rc = amd_pmc_wa_irq1(pdev);
|
||||
|
||||
rc = amd_pmc_wa_irq1(pdev);
|
||||
if (rc) {
|
||||
dev_err(pdev->dev, "failed to adjust keyboard wakeup: %d\n", rc);
|
||||
return rc;
|
||||
|
|
@ -808,6 +728,7 @@ static const struct pci_device_id pmc_pci_ids[] = {
|
|||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SHP) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) },
|
||||
{ }
|
||||
|
|
@ -823,7 +744,6 @@ static int amd_pmc_probe(struct platform_device *pdev)
|
|||
u32 val;
|
||||
|
||||
dev->dev = &pdev->dev;
|
||||
|
||||
rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
|
||||
if (!rdev || !pci_match_id(pmc_pci_ids, rdev)) {
|
||||
err = -ENODEV;
|
||||
|
|
@ -831,8 +751,7 @@ static int amd_pmc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
dev->cpu_id = rdev->device;
|
||||
|
||||
if (dev->cpu_id == AMD_CPU_ID_SP) {
|
||||
if (dev->cpu_id == AMD_CPU_ID_SP || dev->cpu_id == AMD_CPU_ID_SHP) {
|
||||
dev_warn_once(dev->dev, "S0i3 is not supported on this hardware\n");
|
||||
err = -ENODEV;
|
||||
goto err_pci_dev_put;
|
||||
|
|
@ -847,7 +766,6 @@ static int amd_pmc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
base_addr_lo = val & AMD_PMC_BASE_ADDR_HI_MASK;
|
||||
|
||||
err = amd_smn_read(0, AMD_PMC_BASE_ADDR_HI, &val);
|
||||
if (err) {
|
||||
dev_err(dev->dev, "error reading 0x%x\n", AMD_PMC_BASE_ADDR_HI);
|
||||
|
|
@ -865,7 +783,9 @@ static int amd_pmc_probe(struct platform_device *pdev)
|
|||
goto err_pci_dev_put;
|
||||
}
|
||||
|
||||
mutex_init(&dev->lock);
|
||||
err = devm_mutex_init(dev->dev, &dev->lock);
|
||||
if (err)
|
||||
goto err_pci_dev_put;
|
||||
|
||||
/* Get num of IP blocks within the SoC */
|
||||
amd_pmc_get_ip_info(dev);
|
||||
|
|
@ -904,7 +824,6 @@ static void amd_pmc_remove(struct platform_device *pdev)
|
|||
pci_dev_put(dev->rdev);
|
||||
if (IS_ENABLED(CONFIG_AMD_MP2_STB))
|
||||
amd_mp2_stb_deinit(dev);
|
||||
mutex_destroy(&dev->lock);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id amd_pmc_acpi_ids[] = {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,59 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
/* SMU communication registers */
|
||||
#define AMD_PMC_REGISTER_RESPONSE 0x980
|
||||
#define AMD_PMC_REGISTER_ARGUMENT 0x9BC
|
||||
|
||||
/* PMC Scratch Registers */
|
||||
#define AMD_PMC_SCRATCH_REG_CZN 0x94
|
||||
#define AMD_PMC_SCRATCH_REG_YC 0xD14
|
||||
#define AMD_PMC_SCRATCH_REG_1AH 0xF14
|
||||
|
||||
/* STB Registers */
|
||||
#define AMD_PMC_STB_S2IDLE_PREPARE 0xC6000001
|
||||
#define AMD_PMC_STB_S2IDLE_RESTORE 0xC6000002
|
||||
#define AMD_PMC_STB_S2IDLE_CHECK 0xC6000003
|
||||
|
||||
/* Base address of SMU for mapping physical address to virtual address */
|
||||
#define AMD_PMC_MAPPING_SIZE 0x01000
|
||||
#define AMD_PMC_BASE_ADDR_OFFSET 0x10000
|
||||
#define AMD_PMC_BASE_ADDR_LO 0x13B102E8
|
||||
#define AMD_PMC_BASE_ADDR_HI 0x13B102EC
|
||||
#define AMD_PMC_BASE_ADDR_LO_MASK GENMASK(15, 0)
|
||||
#define AMD_PMC_BASE_ADDR_HI_MASK GENMASK(31, 20)
|
||||
|
||||
/* SMU Response Codes */
|
||||
#define AMD_PMC_RESULT_OK 0x01
|
||||
#define AMD_PMC_RESULT_CMD_REJECT_BUSY 0xFC
|
||||
#define AMD_PMC_RESULT_CMD_REJECT_PREREQ 0xFD
|
||||
#define AMD_PMC_RESULT_CMD_UNKNOWN 0xFE
|
||||
#define AMD_PMC_RESULT_FAILED 0xFF
|
||||
|
||||
/* FCH SSC Registers */
|
||||
#define FCH_S0I3_ENTRY_TIME_L_OFFSET 0x30
|
||||
#define FCH_S0I3_ENTRY_TIME_H_OFFSET 0x34
|
||||
#define FCH_S0I3_EXIT_TIME_L_OFFSET 0x38
|
||||
#define FCH_S0I3_EXIT_TIME_H_OFFSET 0x3C
|
||||
#define FCH_SSC_MAPPING_SIZE 0x800
|
||||
#define FCH_BASE_PHY_ADDR_LOW 0xFED81100
|
||||
#define FCH_BASE_PHY_ADDR_HIGH 0x00000000
|
||||
|
||||
/* SMU Message Definations */
|
||||
#define SMU_MSG_GETSMUVERSION 0x02
|
||||
#define SMU_MSG_LOG_GETDRAM_ADDR_HI 0x04
|
||||
#define SMU_MSG_LOG_GETDRAM_ADDR_LO 0x05
|
||||
#define SMU_MSG_LOG_START 0x06
|
||||
#define SMU_MSG_LOG_RESET 0x07
|
||||
#define SMU_MSG_LOG_DUMP_DATA 0x08
|
||||
#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09
|
||||
|
||||
#define PMC_MSG_DELAY_MIN_US 50
|
||||
#define RESPONSE_REGISTER_LOOP_MAX 20000
|
||||
|
||||
#define DELAY_MIN_US 2000
|
||||
#define DELAY_MAX_US 3000
|
||||
|
||||
enum s2d_msg_port {
|
||||
MSG_PORT_PMC,
|
||||
MSG_PORT_S2D,
|
||||
|
|
@ -65,6 +118,34 @@ struct amd_pmc_dev {
|
|||
struct stb_arg stb_arg;
|
||||
};
|
||||
|
||||
struct amd_pmc_bit_map {
|
||||
const char *name;
|
||||
u32 bit_mask;
|
||||
};
|
||||
|
||||
struct smu_metrics {
|
||||
u32 table_version;
|
||||
u32 hint_count;
|
||||
u32 s0i3_last_entry_status;
|
||||
u32 timein_s0i2;
|
||||
u64 timeentering_s0i3_lastcapture;
|
||||
u64 timeentering_s0i3_totaltime;
|
||||
u64 timeto_resume_to_os_lastcapture;
|
||||
u64 timeto_resume_to_os_totaltime;
|
||||
u64 timein_s0i3_lastcapture;
|
||||
u64 timein_s0i3_totaltime;
|
||||
u64 timein_swdrips_lastcapture;
|
||||
u64 timein_swdrips_totaltime;
|
||||
u64 timecondition_notmet_lastcapture[32];
|
||||
u64 timecondition_notmet_totaltime[32];
|
||||
} __packed;
|
||||
|
||||
enum amd_pmc_def {
|
||||
MSG_TEST = 0x01,
|
||||
MSG_OS_HINT_PCO,
|
||||
MSG_OS_HINT_RN,
|
||||
};
|
||||
|
||||
void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
|
||||
void amd_pmc_quirks_init(struct amd_pmc_dev *dev);
|
||||
void amd_mp2_stb_init(struct amd_pmc_dev *dev);
|
||||
|
|
@ -79,6 +160,7 @@ void amd_mp2_stb_deinit(struct amd_pmc_dev *dev);
|
|||
#define AMD_CPU_ID_CB 0x14D8
|
||||
#define AMD_CPU_ID_PS 0x14E8
|
||||
#define AMD_CPU_ID_SP 0x14A4
|
||||
#define AMD_CPU_ID_SHP 0x153A
|
||||
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
|
||||
#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122
|
||||
#define PCI_DEVICE_ID_AMD_MP2_STB 0x172c
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# AMD Platform Management Framework
|
||||
#
|
||||
|
||||
obj-$(CONFIG_AMD_PMF) += amd-pmf.o
|
||||
amd-pmf-objs := core.o acpi.o sps.o \
|
||||
auto-mode.o cnqf.o \
|
||||
tee-if.o spc.o
|
||||
obj-$(CONFIG_AMD_PMF) += amd-pmf.o
|
||||
amd-pmf-y := core.o acpi.o sps.o \
|
||||
auto-mode.o cnqf.o \
|
||||
tee-if.o spc.o
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ static void apmf_sbios_heartbeat_notify(struct work_struct *work)
|
|||
if (!info)
|
||||
return;
|
||||
|
||||
schedule_delayed_work(&dev->heart_beat, msecs_to_jiffies(dev->hb_interval * 1000));
|
||||
schedule_delayed_work(&dev->heart_beat, secs_to_jiffies(dev->hb_interval));
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -856,7 +856,7 @@ static int tf103c_dock_probe(struct i2c_client *client)
|
|||
/* 5. Setup irqchip for touchpad IRQ pass-through */
|
||||
dock->tp_irqchip.name = KBUILD_MODNAME;
|
||||
|
||||
dock->tp_irq_domain = irq_domain_add_linear(NULL, 1, &irq_domain_simple_ops, NULL);
|
||||
dock->tp_irq_domain = irq_domain_create_linear(NULL, 1, &irq_domain_simple_ops, NULL);
|
||||
if (!dock->tp_irq_domain)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@
|
|||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/fb.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
/* ======= */
|
||||
|
|
|
|||
|
|
@ -18,15 +18,35 @@ config ALIENWARE_WMI
|
|||
tristate "Alienware Special feature control"
|
||||
default m
|
||||
depends on ACPI
|
||||
depends on ACPI_WMI
|
||||
depends on DMI
|
||||
depends on LEDS_CLASS
|
||||
depends on NEW_LEDS
|
||||
depends on ACPI_WMI
|
||||
help
|
||||
This is a driver for controlling Alienware WMI driven features.
|
||||
|
||||
On legacy devices, it exposes an interface for controlling the AlienFX
|
||||
zones on Alienware machines that don't contain a dedicated
|
||||
AlienFX USB MCU such as the X51 and X51-R2.
|
||||
|
||||
On newer devices, it exposes the AWCC thermal control interface through
|
||||
known Kernel APIs.
|
||||
|
||||
config ALIENWARE_WMI_LEGACY
|
||||
bool "Alienware Legacy WMI device driver"
|
||||
default y
|
||||
depends on ALIENWARE_WMI
|
||||
help
|
||||
Legacy Alienware WMI driver with AlienFX LED control capabilities.
|
||||
|
||||
config ALIENWARE_WMI_WMAX
|
||||
bool "Alienware WMAX WMI device driver"
|
||||
default y
|
||||
depends on ALIENWARE_WMI
|
||||
select ACPI_PLATFORM_PROFILE
|
||||
help
|
||||
This is a driver for controlling Alienware BIOS driven
|
||||
features. It exposes an interface for controlling the AlienFX
|
||||
zones on Alienware machines that don't contain a dedicated AlienFX
|
||||
USB MCU such as the X51 and X51-R2.
|
||||
Alienware WMI driver with AlienFX LED, HDMI, amplifier, deep sleep and
|
||||
AWCC thermal control capabilities.
|
||||
|
||||
config DCDBAS
|
||||
tristate "Dell Systems Management Base Driver"
|
||||
|
|
|
|||
|
|
@ -4,24 +4,27 @@
|
|||
# Dell x86 Platform-Specific Drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
|
||||
obj-$(CONFIG_DCDBAS) += dcdbas.o
|
||||
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
|
||||
obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
|
||||
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
|
||||
obj-$(CONFIG_DELL_PC) += dell-pc.o
|
||||
obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
|
||||
dell-smbios-objs := dell-smbios-base.o
|
||||
dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
|
||||
dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o
|
||||
obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
|
||||
obj-$(CONFIG_DELL_SMO8800) += dell-lis3lv02d.o
|
||||
obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o
|
||||
obj-$(CONFIG_DELL_WMI) += dell-wmi.o
|
||||
dell-wmi-objs := dell-wmi-base.o
|
||||
dell-wmi-$(CONFIG_DELL_WMI_PRIVACY) += dell-wmi-privacy.o
|
||||
obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
|
||||
obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
|
||||
obj-$(CONFIG_DELL_WMI_DDV) += dell-wmi-ddv.o
|
||||
obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
|
||||
obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/
|
||||
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
|
||||
alienware-wmi-y := alienware-wmi-base.o
|
||||
alienware-wmi-$(CONFIG_ALIENWARE_WMI_LEGACY) += alienware-wmi-legacy.o
|
||||
alienware-wmi-$(CONFIG_ALIENWARE_WMI_WMAX) += alienware-wmi-wmax.o
|
||||
obj-$(CONFIG_DCDBAS) += dcdbas.o
|
||||
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
|
||||
obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
|
||||
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
|
||||
obj-$(CONFIG_DELL_PC) += dell-pc.o
|
||||
obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
|
||||
dell-smbios-y := dell-smbios-base.o
|
||||
dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
|
||||
dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o
|
||||
obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
|
||||
obj-$(CONFIG_DELL_SMO8800) += dell-lis3lv02d.o
|
||||
obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o
|
||||
obj-$(CONFIG_DELL_WMI) += dell-wmi.o
|
||||
dell-wmi-y := dell-wmi-base.o
|
||||
dell-wmi-$(CONFIG_DELL_WMI_PRIVACY) += dell-wmi-privacy.o
|
||||
obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
|
||||
obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
|
||||
obj-$(CONFIG_DELL_WMI_DDV) += dell-wmi-ddv.o
|
||||
obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
|
||||
obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/
|
||||
|
|
|
|||
491
drivers/platform/x86/dell/alienware-wmi-base.c
Normal file
491
drivers/platform/x86/dell/alienware-wmi-base.c
Normal file
|
|
@ -0,0 +1,491 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Alienware special feature control
|
||||
*
|
||||
* Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com>
|
||||
* Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/leds.h>
|
||||
#include "alienware-wmi.h"
|
||||
|
||||
MODULE_AUTHOR("Mario Limonciello <mario.limonciello@outlook.com>");
|
||||
MODULE_AUTHOR("Kurt Borja <kuurtb@gmail.com>");
|
||||
MODULE_DESCRIPTION("Alienware special feature control");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct alienfx_quirks *alienfx;
|
||||
|
||||
static struct alienfx_quirks quirk_inspiron5675 = {
|
||||
.num_zones = 2,
|
||||
.hdmi_mux = false,
|
||||
.amplifier = false,
|
||||
.deepslp = false,
|
||||
};
|
||||
|
||||
static struct alienfx_quirks quirk_unknown = {
|
||||
.num_zones = 2,
|
||||
.hdmi_mux = false,
|
||||
.amplifier = false,
|
||||
.deepslp = false,
|
||||
};
|
||||
|
||||
static struct alienfx_quirks quirk_x51_r1_r2 = {
|
||||
.num_zones = 3,
|
||||
.hdmi_mux = false,
|
||||
.amplifier = false,
|
||||
.deepslp = false,
|
||||
};
|
||||
|
||||
static struct alienfx_quirks quirk_x51_r3 = {
|
||||
.num_zones = 4,
|
||||
.hdmi_mux = false,
|
||||
.amplifier = true,
|
||||
.deepslp = false,
|
||||
};
|
||||
|
||||
static struct alienfx_quirks quirk_asm100 = {
|
||||
.num_zones = 2,
|
||||
.hdmi_mux = true,
|
||||
.amplifier = false,
|
||||
.deepslp = false,
|
||||
};
|
||||
|
||||
static struct alienfx_quirks quirk_asm200 = {
|
||||
.num_zones = 2,
|
||||
.hdmi_mux = true,
|
||||
.amplifier = false,
|
||||
.deepslp = true,
|
||||
};
|
||||
|
||||
static struct alienfx_quirks quirk_asm201 = {
|
||||
.num_zones = 2,
|
||||
.hdmi_mux = true,
|
||||
.amplifier = true,
|
||||
.deepslp = true,
|
||||
};
|
||||
|
||||
static int __init dmi_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
alienfx = dmi->driver_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id alienware_quirks[] __initconst = {
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Alienware ASM100",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"),
|
||||
},
|
||||
.driver_data = &quirk_asm100,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Alienware ASM200",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"),
|
||||
},
|
||||
.driver_data = &quirk_asm200,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Alienware ASM201",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"),
|
||||
},
|
||||
.driver_data = &quirk_asm201,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Alienware X51 R1",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"),
|
||||
},
|
||||
.driver_data = &quirk_x51_r1_r2,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Alienware X51 R2",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"),
|
||||
},
|
||||
.driver_data = &quirk_x51_r1_r2,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Alienware X51 R3",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"),
|
||||
},
|
||||
.driver_data = &quirk_x51_r3,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "Dell Inc. Inspiron 5675",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5675"),
|
||||
},
|
||||
.driver_data = &quirk_inspiron5675,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
u8 alienware_interface;
|
||||
|
||||
int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
|
||||
void *in_args, size_t in_size, u32 *out_data)
|
||||
{
|
||||
struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
struct acpi_buffer in = {in_size, in_args};
|
||||
acpi_status ret;
|
||||
|
||||
ret = wmidev_evaluate_method(wdev, 0, method_id, &in, out_data ? &out : NULL);
|
||||
if (ACPI_FAILURE(ret))
|
||||
return -EIO;
|
||||
|
||||
union acpi_object *obj __free(kfree) = out.pointer;
|
||||
|
||||
if (out_data) {
|
||||
if (obj && obj->type == ACPI_TYPE_INTEGER)
|
||||
*out_data = (u32)obj->integer.value;
|
||||
else
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers used for zone control
|
||||
*/
|
||||
static int parse_rgb(const char *buf, struct color_platform *colors)
|
||||
{
|
||||
long unsigned int rgb;
|
||||
int ret;
|
||||
union color_union {
|
||||
struct color_platform cp;
|
||||
int package;
|
||||
} repackager;
|
||||
|
||||
ret = kstrtoul(buf, 16, &rgb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* RGB triplet notation is 24-bit hexadecimal */
|
||||
if (rgb > 0xFFFFFF)
|
||||
return -EINVAL;
|
||||
|
||||
repackager.package = rgb & 0x0f0f0f0f;
|
||||
pr_debug("alienware-wmi: r: %d g:%d b: %d\n",
|
||||
repackager.cp.red, repackager.cp.green, repackager.cp.blue);
|
||||
*colors = repackager.cp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Individual RGB zone control
|
||||
*/
|
||||
static ssize_t zone_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf, u8 location)
|
||||
{
|
||||
struct alienfx_priv *priv = dev_get_drvdata(dev);
|
||||
struct color_platform *colors = &priv->colors[location];
|
||||
|
||||
return sprintf(buf, "red: %d, green: %d, blue: %d\n",
|
||||
colors->red, colors->green, colors->blue);
|
||||
|
||||
}
|
||||
|
||||
static ssize_t zone_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count, u8 location)
|
||||
{
|
||||
struct alienfx_priv *priv = dev_get_drvdata(dev);
|
||||
struct color_platform *colors = &priv->colors[location];
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = parse_rgb(buf, colors);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pdata->ops.upd_led(priv, pdata->wdev, location);
|
||||
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static ssize_t zone00_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return zone_show(dev, attr, buf, 0);
|
||||
}
|
||||
|
||||
static ssize_t zone00_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return zone_store(dev, attr, buf, count, 0);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(zone00);
|
||||
|
||||
static ssize_t zone01_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return zone_show(dev, attr, buf, 1);
|
||||
}
|
||||
|
||||
static ssize_t zone01_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return zone_store(dev, attr, buf, count, 1);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(zone01);
|
||||
|
||||
static ssize_t zone02_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return zone_show(dev, attr, buf, 2);
|
||||
}
|
||||
|
||||
static ssize_t zone02_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return zone_store(dev, attr, buf, count, 2);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(zone02);
|
||||
|
||||
static ssize_t zone03_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return zone_show(dev, attr, buf, 3);
|
||||
}
|
||||
|
||||
static ssize_t zone03_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return zone_store(dev, attr, buf, count, 3);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(zone03);
|
||||
|
||||
/*
|
||||
* Lighting control state device attribute (Global)
|
||||
*/
|
||||
static ssize_t lighting_control_state_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct alienfx_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (priv->lighting_control_state == LEGACY_BOOTING)
|
||||
return sysfs_emit(buf, "[booting] running suspend\n");
|
||||
else if (priv->lighting_control_state == LEGACY_SUSPEND)
|
||||
return sysfs_emit(buf, "booting running [suspend]\n");
|
||||
|
||||
return sysfs_emit(buf, "booting [running] suspend\n");
|
||||
}
|
||||
|
||||
static ssize_t lighting_control_state_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct alienfx_priv *priv = dev_get_drvdata(dev);
|
||||
u8 val;
|
||||
|
||||
if (strcmp(buf, "booting\n") == 0)
|
||||
val = LEGACY_BOOTING;
|
||||
else if (strcmp(buf, "suspend\n") == 0)
|
||||
val = LEGACY_SUSPEND;
|
||||
else if (alienware_interface == LEGACY)
|
||||
val = LEGACY_RUNNING;
|
||||
else
|
||||
val = WMAX_RUNNING;
|
||||
|
||||
priv->lighting_control_state = val;
|
||||
pr_debug("alienware-wmi: updated control state to %d\n",
|
||||
priv->lighting_control_state);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(lighting_control_state);
|
||||
|
||||
static umode_t zone_attr_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
if (n < alienfx->num_zones + 1)
|
||||
return attr->mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool zone_group_visible(struct kobject *kobj)
|
||||
{
|
||||
return alienfx->num_zones > 0;
|
||||
}
|
||||
DEFINE_SYSFS_GROUP_VISIBLE(zone);
|
||||
|
||||
static struct attribute *zone_attrs[] = {
|
||||
&dev_attr_lighting_control_state.attr,
|
||||
&dev_attr_zone00.attr,
|
||||
&dev_attr_zone01.attr,
|
||||
&dev_attr_zone02.attr,
|
||||
&dev_attr_zone03.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group zone_attribute_group = {
|
||||
.name = "rgb_zones",
|
||||
.is_visible = SYSFS_GROUP_VISIBLE(zone),
|
||||
.attrs = zone_attrs,
|
||||
};
|
||||
|
||||
/*
|
||||
* LED Brightness (Global)
|
||||
*/
|
||||
static void global_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct alienfx_priv *priv = container_of(led_cdev, struct alienfx_priv,
|
||||
global_led);
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(&priv->pdev->dev);
|
||||
int ret;
|
||||
|
||||
priv->global_brightness = brightness;
|
||||
|
||||
ret = pdata->ops.upd_brightness(priv, pdata->wdev, brightness);
|
||||
if (ret)
|
||||
pr_err("LED brightness update failed\n");
|
||||
}
|
||||
|
||||
static enum led_brightness global_led_get(struct led_classdev *led_cdev)
|
||||
{
|
||||
struct alienfx_priv *priv = container_of(led_cdev, struct alienfx_priv,
|
||||
global_led);
|
||||
|
||||
return priv->global_brightness;
|
||||
}
|
||||
|
||||
/*
|
||||
* Platform Driver
|
||||
*/
|
||||
static int alienfx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct alienfx_priv *priv;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
if (alienware_interface == WMAX)
|
||||
priv->lighting_control_state = WMAX_RUNNING;
|
||||
else
|
||||
priv->lighting_control_state = LEGACY_RUNNING;
|
||||
|
||||
priv->pdev = pdev;
|
||||
priv->global_led.name = "alienware::global_brightness";
|
||||
priv->global_led.brightness_set = global_led_set;
|
||||
priv->global_led.brightness_get = global_led_get;
|
||||
priv->global_led.max_brightness = 0x0F;
|
||||
priv->global_brightness = priv->global_led.max_brightness;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
return devm_led_classdev_register(&pdev->dev, &priv->global_led);
|
||||
}
|
||||
|
||||
static const struct attribute_group *alienfx_groups[] = {
|
||||
&zone_attribute_group,
|
||||
WMAX_DEV_GROUPS
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct platform_driver platform_driver = {
|
||||
.driver = {
|
||||
.name = "alienware-wmi",
|
||||
.dev_groups = alienfx_groups,
|
||||
},
|
||||
.probe = alienfx_probe,
|
||||
};
|
||||
|
||||
static void alienware_alienfx_remove(void *data)
|
||||
{
|
||||
struct platform_device *pdev = data;
|
||||
|
||||
platform_device_unregister(pdev);
|
||||
}
|
||||
|
||||
int alienware_alienfx_setup(struct alienfx_platdata *pdata)
|
||||
{
|
||||
struct device *dev = &pdata->wdev->dev;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
pdev = platform_device_register_data(NULL, "alienware-wmi",
|
||||
PLATFORM_DEVID_NONE, pdata,
|
||||
sizeof(*pdata));
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
|
||||
dev_set_drvdata(dev, pdev);
|
||||
ret = devm_add_action_or_reset(dev, alienware_alienfx_remove, pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init alienware_wmi_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dmi_check_system(alienware_quirks);
|
||||
if (!alienfx)
|
||||
alienfx = &quirk_unknown;
|
||||
|
||||
ret = platform_driver_register(&platform_driver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (wmi_has_guid(WMAX_CONTROL_GUID)) {
|
||||
alienware_interface = WMAX;
|
||||
ret = alienware_wmax_wmi_init();
|
||||
} else {
|
||||
alienware_interface = LEGACY;
|
||||
ret = alienware_legacy_wmi_init();
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
platform_driver_unregister(&platform_driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
module_init(alienware_wmi_init);
|
||||
|
||||
static void __exit alienware_wmi_exit(void)
|
||||
{
|
||||
if (alienware_interface == WMAX)
|
||||
alienware_wmax_wmi_exit();
|
||||
else
|
||||
alienware_legacy_wmi_exit();
|
||||
|
||||
platform_driver_unregister(&platform_driver);
|
||||
}
|
||||
|
||||
module_exit(alienware_wmi_exit);
|
||||
95
drivers/platform/x86/dell/alienware-wmi-legacy.c
Normal file
95
drivers/platform/x86/dell/alienware-wmi-legacy.c
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Alienware LEGACY WMI device driver
|
||||
*
|
||||
* Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/wmi.h>
|
||||
#include "alienware-wmi.h"
|
||||
|
||||
struct legacy_led_args {
|
||||
struct color_platform colors;
|
||||
u8 brightness;
|
||||
u8 state;
|
||||
} __packed;
|
||||
|
||||
|
||||
/*
|
||||
* Legacy WMI driver
|
||||
*/
|
||||
static int legacy_wmi_update_led(struct alienfx_priv *priv,
|
||||
struct wmi_device *wdev, u8 location)
|
||||
{
|
||||
struct legacy_led_args legacy_args = {
|
||||
.colors = priv->colors[location],
|
||||
.brightness = priv->global_brightness,
|
||||
.state = 0,
|
||||
};
|
||||
struct acpi_buffer input;
|
||||
acpi_status status;
|
||||
|
||||
if (legacy_args.state != LEGACY_RUNNING) {
|
||||
legacy_args.state = priv->lighting_control_state;
|
||||
|
||||
input.length = sizeof(legacy_args);
|
||||
input.pointer = &legacy_args;
|
||||
|
||||
status = wmi_evaluate_method(LEGACY_POWER_CONTROL_GUID, 0,
|
||||
location + 1, &input, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return alienware_wmi_command(wdev, location + 1, &legacy_args,
|
||||
sizeof(legacy_args), NULL);
|
||||
}
|
||||
|
||||
static int legacy_wmi_update_brightness(struct alienfx_priv *priv,
|
||||
struct wmi_device *wdev, u8 brightness)
|
||||
{
|
||||
return legacy_wmi_update_led(priv, wdev, 0);
|
||||
}
|
||||
|
||||
static int legacy_wmi_probe(struct wmi_device *wdev, const void *context)
|
||||
{
|
||||
struct alienfx_platdata pdata = {
|
||||
.wdev = wdev,
|
||||
.ops = {
|
||||
.upd_led = legacy_wmi_update_led,
|
||||
.upd_brightness = legacy_wmi_update_brightness,
|
||||
},
|
||||
};
|
||||
|
||||
return alienware_alienfx_setup(&pdata);
|
||||
}
|
||||
|
||||
static const struct wmi_device_id alienware_legacy_device_id_table[] = {
|
||||
{ LEGACY_CONTROL_GUID, NULL },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(wmi, alienware_legacy_device_id_table);
|
||||
|
||||
static struct wmi_driver alienware_legacy_wmi_driver = {
|
||||
.driver = {
|
||||
.name = "alienware-wmi-alienfx",
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
},
|
||||
.id_table = alienware_legacy_device_id_table,
|
||||
.probe = legacy_wmi_probe,
|
||||
.no_singleton = true,
|
||||
};
|
||||
|
||||
int __init alienware_legacy_wmi_init(void)
|
||||
{
|
||||
return wmi_driver_register(&alienware_legacy_wmi_driver);
|
||||
}
|
||||
|
||||
void __exit alienware_legacy_wmi_exit(void)
|
||||
{
|
||||
wmi_driver_unregister(&alienware_legacy_wmi_driver);
|
||||
}
|
||||
768
drivers/platform/x86/dell/alienware-wmi-wmax.c
Normal file
768
drivers/platform/x86/dell/alienware-wmi-wmax.c
Normal file
|
|
@ -0,0 +1,768 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Alienware WMAX WMI device driver
|
||||
*
|
||||
* Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com>
|
||||
* Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/platform_profile.h>
|
||||
#include <linux/wmi.h>
|
||||
#include "alienware-wmi.h"
|
||||
|
||||
#define WMAX_METHOD_HDMI_SOURCE 0x1
|
||||
#define WMAX_METHOD_HDMI_STATUS 0x2
|
||||
#define WMAX_METHOD_HDMI_CABLE 0x5
|
||||
#define WMAX_METHOD_AMPLIFIER_CABLE 0x6
|
||||
#define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B
|
||||
#define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C
|
||||
#define WMAX_METHOD_BRIGHTNESS 0x3
|
||||
#define WMAX_METHOD_ZONE_CONTROL 0x4
|
||||
#define WMAX_METHOD_THERMAL_INFORMATION 0x14
|
||||
#define WMAX_METHOD_THERMAL_CONTROL 0x15
|
||||
#define WMAX_METHOD_GAME_SHIFT_STATUS 0x25
|
||||
|
||||
#define WMAX_THERMAL_MODE_GMODE 0xAB
|
||||
|
||||
#define WMAX_FAILURE_CODE 0xFFFFFFFF
|
||||
#define WMAX_THERMAL_TABLE_MASK GENMASK(7, 4)
|
||||
#define WMAX_THERMAL_MODE_MASK GENMASK(3, 0)
|
||||
#define WMAX_SENSOR_ID_MASK BIT(8)
|
||||
|
||||
static bool force_platform_profile;
|
||||
module_param_unsafe(force_platform_profile, bool, 0);
|
||||
MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available");
|
||||
|
||||
static bool force_gmode;
|
||||
module_param_unsafe(force_gmode, bool, 0);
|
||||
MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
|
||||
|
||||
struct awcc_quirks {
|
||||
bool pprof;
|
||||
bool gmode;
|
||||
};
|
||||
|
||||
static struct awcc_quirks g_series_quirks = {
|
||||
.pprof = true,
|
||||
.gmode = true,
|
||||
};
|
||||
|
||||
static struct awcc_quirks generic_quirks = {
|
||||
.pprof = true,
|
||||
.gmode = false,
|
||||
};
|
||||
|
||||
static struct awcc_quirks empty_quirks;
|
||||
|
||||
static const struct dmi_system_id awcc_dmi_table[] __initconst = {
|
||||
{
|
||||
.ident = "Alienware m16 R1 AMD",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
|
||||
},
|
||||
.driver_data = &generic_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Alienware m17 R5",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
|
||||
},
|
||||
.driver_data = &generic_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Alienware m18 R2",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"),
|
||||
},
|
||||
.driver_data = &generic_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Alienware x15 R1",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"),
|
||||
},
|
||||
.driver_data = &generic_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Alienware x17 R2",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"),
|
||||
},
|
||||
.driver_data = &generic_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Dell Inc. G15 5510",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"),
|
||||
},
|
||||
.driver_data = &g_series_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Dell Inc. G15 5511",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"),
|
||||
},
|
||||
.driver_data = &g_series_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Dell Inc. G15 5515",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
|
||||
},
|
||||
.driver_data = &g_series_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Dell Inc. G3 3500",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"),
|
||||
},
|
||||
.driver_data = &g_series_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Dell Inc. G3 3590",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"),
|
||||
},
|
||||
.driver_data = &g_series_quirks,
|
||||
},
|
||||
{
|
||||
.ident = "Dell Inc. G5 5500",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"),
|
||||
},
|
||||
.driver_data = &g_series_quirks,
|
||||
},
|
||||
};
|
||||
|
||||
enum WMAX_THERMAL_INFORMATION_OPERATIONS {
|
||||
WMAX_OPERATION_SYS_DESCRIPTION = 0x02,
|
||||
WMAX_OPERATION_LIST_IDS = 0x03,
|
||||
WMAX_OPERATION_CURRENT_PROFILE = 0x0B,
|
||||
};
|
||||
|
||||
enum WMAX_THERMAL_CONTROL_OPERATIONS {
|
||||
WMAX_OPERATION_ACTIVATE_PROFILE = 0x01,
|
||||
};
|
||||
|
||||
enum WMAX_GAME_SHIFT_STATUS_OPERATIONS {
|
||||
WMAX_OPERATION_TOGGLE_GAME_SHIFT = 0x01,
|
||||
WMAX_OPERATION_GET_GAME_SHIFT_STATUS = 0x02,
|
||||
};
|
||||
|
||||
enum WMAX_THERMAL_TABLES {
|
||||
WMAX_THERMAL_TABLE_BASIC = 0x90,
|
||||
WMAX_THERMAL_TABLE_USTT = 0xA0,
|
||||
};
|
||||
|
||||
enum wmax_thermal_mode {
|
||||
THERMAL_MODE_USTT_BALANCED,
|
||||
THERMAL_MODE_USTT_BALANCED_PERFORMANCE,
|
||||
THERMAL_MODE_USTT_COOL,
|
||||
THERMAL_MODE_USTT_QUIET,
|
||||
THERMAL_MODE_USTT_PERFORMANCE,
|
||||
THERMAL_MODE_USTT_LOW_POWER,
|
||||
THERMAL_MODE_BASIC_QUIET,
|
||||
THERMAL_MODE_BASIC_BALANCED,
|
||||
THERMAL_MODE_BASIC_BALANCED_PERFORMANCE,
|
||||
THERMAL_MODE_BASIC_PERFORMANCE,
|
||||
THERMAL_MODE_LAST,
|
||||
};
|
||||
|
||||
struct wmax_led_args {
|
||||
u32 led_mask;
|
||||
struct color_platform colors;
|
||||
u8 state;
|
||||
} __packed;
|
||||
|
||||
struct wmax_brightness_args {
|
||||
u32 led_mask;
|
||||
u32 percentage;
|
||||
};
|
||||
|
||||
struct wmax_basic_args {
|
||||
u8 arg;
|
||||
};
|
||||
|
||||
struct wmax_u32_args {
|
||||
u8 operation;
|
||||
u8 arg1;
|
||||
u8 arg2;
|
||||
u8 arg3;
|
||||
};
|
||||
|
||||
struct awcc_priv {
|
||||
struct wmi_device *wdev;
|
||||
struct device *ppdev;
|
||||
enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
|
||||
};
|
||||
|
||||
static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_MODE_LAST] = {
|
||||
[THERMAL_MODE_USTT_BALANCED] = PLATFORM_PROFILE_BALANCED,
|
||||
[THERMAL_MODE_USTT_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
|
||||
[THERMAL_MODE_USTT_COOL] = PLATFORM_PROFILE_COOL,
|
||||
[THERMAL_MODE_USTT_QUIET] = PLATFORM_PROFILE_QUIET,
|
||||
[THERMAL_MODE_USTT_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
|
||||
[THERMAL_MODE_USTT_LOW_POWER] = PLATFORM_PROFILE_LOW_POWER,
|
||||
[THERMAL_MODE_BASIC_QUIET] = PLATFORM_PROFILE_QUIET,
|
||||
[THERMAL_MODE_BASIC_BALANCED] = PLATFORM_PROFILE_BALANCED,
|
||||
[THERMAL_MODE_BASIC_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
|
||||
[THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
|
||||
};
|
||||
|
||||
static struct awcc_quirks *awcc;
|
||||
|
||||
/*
|
||||
* The HDMI mux sysfs node indicates the status of the HDMI input mux.
|
||||
* It can toggle between standard system GPU output and HDMI input.
|
||||
*/
|
||||
static ssize_t cable_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(dev);
|
||||
struct wmax_basic_args in_args = {
|
||||
.arg = 0,
|
||||
};
|
||||
u32 out_data;
|
||||
int ret;
|
||||
|
||||
ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE,
|
||||
&in_args, sizeof(in_args), &out_data);
|
||||
if (!ret) {
|
||||
if (out_data == 0)
|
||||
return sysfs_emit(buf, "[unconnected] connected unknown\n");
|
||||
else if (out_data == 1)
|
||||
return sysfs_emit(buf, "unconnected [connected] unknown\n");
|
||||
}
|
||||
|
||||
pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret);
|
||||
return sysfs_emit(buf, "unconnected connected [unknown]\n");
|
||||
}
|
||||
|
||||
static ssize_t source_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(dev);
|
||||
struct wmax_basic_args in_args = {
|
||||
.arg = 0,
|
||||
};
|
||||
u32 out_data;
|
||||
int ret;
|
||||
|
||||
ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS,
|
||||
&in_args, sizeof(in_args), &out_data);
|
||||
if (!ret) {
|
||||
if (out_data == 1)
|
||||
return sysfs_emit(buf, "[input] gpu unknown\n");
|
||||
else if (out_data == 2)
|
||||
return sysfs_emit(buf, "input [gpu] unknown\n");
|
||||
}
|
||||
|
||||
pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret);
|
||||
return sysfs_emit(buf, "input gpu [unknown]\n");
|
||||
}
|
||||
|
||||
static ssize_t source_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(dev);
|
||||
struct wmax_basic_args args;
|
||||
int ret;
|
||||
|
||||
if (strcmp(buf, "gpu\n") == 0)
|
||||
args.arg = 1;
|
||||
else if (strcmp(buf, "input\n") == 0)
|
||||
args.arg = 2;
|
||||
else
|
||||
args.arg = 3;
|
||||
pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
|
||||
|
||||
ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args,
|
||||
sizeof(args), NULL);
|
||||
if (ret < 0)
|
||||
pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(cable);
|
||||
static DEVICE_ATTR_RW(source);
|
||||
|
||||
static bool hdmi_group_visible(struct kobject *kobj)
|
||||
{
|
||||
return alienware_interface == WMAX && alienfx->hdmi_mux;
|
||||
}
|
||||
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi);
|
||||
|
||||
static struct attribute *hdmi_attrs[] = {
|
||||
&dev_attr_cable.attr,
|
||||
&dev_attr_source.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const struct attribute_group wmax_hdmi_attribute_group = {
|
||||
.name = "hdmi",
|
||||
.is_visible = SYSFS_GROUP_VISIBLE(hdmi),
|
||||
.attrs = hdmi_attrs,
|
||||
};
|
||||
|
||||
/*
|
||||
* Alienware GFX amplifier support
|
||||
* - Currently supports reading cable status
|
||||
* - Leaving expansion room to possibly support dock/undock events later
|
||||
*/
|
||||
static ssize_t status_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(dev);
|
||||
struct wmax_basic_args in_args = {
|
||||
.arg = 0,
|
||||
};
|
||||
u32 out_data;
|
||||
int ret;
|
||||
|
||||
ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE,
|
||||
&in_args, sizeof(in_args), &out_data);
|
||||
if (!ret) {
|
||||
if (out_data == 0)
|
||||
return sysfs_emit(buf, "[unconnected] connected unknown\n");
|
||||
else if (out_data == 1)
|
||||
return sysfs_emit(buf, "unconnected [connected] unknown\n");
|
||||
}
|
||||
|
||||
pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret);
|
||||
return sysfs_emit(buf, "unconnected connected [unknown]\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(status);
|
||||
|
||||
static bool amplifier_group_visible(struct kobject *kobj)
|
||||
{
|
||||
return alienware_interface == WMAX && alienfx->amplifier;
|
||||
}
|
||||
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier);
|
||||
|
||||
static struct attribute *amplifier_attrs[] = {
|
||||
&dev_attr_status.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const struct attribute_group wmax_amplifier_attribute_group = {
|
||||
.name = "amplifier",
|
||||
.is_visible = SYSFS_GROUP_VISIBLE(amplifier),
|
||||
.attrs = amplifier_attrs,
|
||||
};
|
||||
|
||||
/*
|
||||
* Deep Sleep Control support
|
||||
* - Modifies BIOS setting for deep sleep control allowing extra wakeup events
|
||||
*/
|
||||
static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(dev);
|
||||
struct wmax_basic_args in_args = {
|
||||
.arg = 0,
|
||||
};
|
||||
u32 out_data;
|
||||
int ret;
|
||||
|
||||
ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS,
|
||||
&in_args, sizeof(in_args), &out_data);
|
||||
if (!ret) {
|
||||
if (out_data == 0)
|
||||
return sysfs_emit(buf, "[disabled] s5 s5_s4\n");
|
||||
else if (out_data == 1)
|
||||
return sysfs_emit(buf, "disabled [s5] s5_s4\n");
|
||||
else if (out_data == 2)
|
||||
return sysfs_emit(buf, "disabled s5 [s5_s4]\n");
|
||||
}
|
||||
|
||||
pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret);
|
||||
return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n");
|
||||
}
|
||||
|
||||
static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct alienfx_platdata *pdata = dev_get_platdata(dev);
|
||||
struct wmax_basic_args args;
|
||||
int ret;
|
||||
|
||||
if (strcmp(buf, "disabled\n") == 0)
|
||||
args.arg = 0;
|
||||
else if (strcmp(buf, "s5\n") == 0)
|
||||
args.arg = 1;
|
||||
else
|
||||
args.arg = 2;
|
||||
pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf);
|
||||
|
||||
ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL,
|
||||
&args, sizeof(args), NULL);
|
||||
if (!ret)
|
||||
pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(deepsleep);
|
||||
|
||||
static bool deepsleep_group_visible(struct kobject *kobj)
|
||||
{
|
||||
return alienware_interface == WMAX && alienfx->deepslp;
|
||||
}
|
||||
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep);
|
||||
|
||||
static struct attribute *deepsleep_attrs[] = {
|
||||
&dev_attr_deepsleep.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const struct attribute_group wmax_deepsleep_attribute_group = {
|
||||
.name = "deepsleep",
|
||||
.is_visible = SYSFS_GROUP_VISIBLE(deepsleep),
|
||||
.attrs = deepsleep_attrs,
|
||||
};
|
||||
|
||||
/*
|
||||
* Thermal Profile control
|
||||
* - Provides thermal profile control through the Platform Profile API
|
||||
*/
|
||||
static bool is_wmax_thermal_code(u32 code)
|
||||
{
|
||||
if (code & WMAX_SENSOR_ID_MASK)
|
||||
return false;
|
||||
|
||||
if ((code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_LAST)
|
||||
return false;
|
||||
|
||||
if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_BASIC &&
|
||||
(code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_BASIC_QUIET)
|
||||
return true;
|
||||
|
||||
if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_USTT &&
|
||||
(code & WMAX_THERMAL_MODE_MASK) <= THERMAL_MODE_USTT_LOW_POWER)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int wmax_thermal_information(struct wmi_device *wdev, u8 operation,
|
||||
u8 arg, u32 *out_data)
|
||||
{
|
||||
struct wmax_u32_args in_args = {
|
||||
.operation = operation,
|
||||
.arg1 = arg,
|
||||
.arg2 = 0,
|
||||
.arg3 = 0,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_INFORMATION,
|
||||
&in_args, sizeof(in_args), out_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (*out_data == WMAX_FAILURE_CODE)
|
||||
return -EBADRQC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wmax_thermal_control(struct wmi_device *wdev, u8 profile)
|
||||
{
|
||||
struct wmax_u32_args in_args = {
|
||||
.operation = WMAX_OPERATION_ACTIVATE_PROFILE,
|
||||
.arg1 = profile,
|
||||
.arg2 = 0,
|
||||
.arg3 = 0,
|
||||
};
|
||||
u32 out_data;
|
||||
int ret;
|
||||
|
||||
ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_CONTROL,
|
||||
&in_args, sizeof(in_args), &out_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (out_data == WMAX_FAILURE_CODE)
|
||||
return -EBADRQC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wmax_game_shift_status(struct wmi_device *wdev, u8 operation,
|
||||
u32 *out_data)
|
||||
{
|
||||
struct wmax_u32_args in_args = {
|
||||
.operation = operation,
|
||||
.arg1 = 0,
|
||||
.arg2 = 0,
|
||||
.arg3 = 0,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = alienware_wmi_command(wdev, WMAX_METHOD_GAME_SHIFT_STATUS,
|
||||
&in_args, sizeof(in_args), out_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (*out_data == WMAX_FAILURE_CODE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thermal_profile_get(struct device *dev,
|
||||
enum platform_profile_option *profile)
|
||||
{
|
||||
struct awcc_priv *priv = dev_get_drvdata(dev);
|
||||
u32 out_data;
|
||||
int ret;
|
||||
|
||||
ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_CURRENT_PROFILE,
|
||||
0, &out_data);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (out_data == WMAX_THERMAL_MODE_GMODE) {
|
||||
*profile = PLATFORM_PROFILE_PERFORMANCE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!is_wmax_thermal_code(out_data))
|
||||
return -ENODATA;
|
||||
|
||||
out_data &= WMAX_THERMAL_MODE_MASK;
|
||||
*profile = wmax_mode_to_platform_profile[out_data];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thermal_profile_set(struct device *dev,
|
||||
enum platform_profile_option profile)
|
||||
{
|
||||
struct awcc_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (awcc->gmode) {
|
||||
u32 gmode_status;
|
||||
int ret;
|
||||
|
||||
ret = wmax_game_shift_status(priv->wdev,
|
||||
WMAX_OPERATION_GET_GAME_SHIFT_STATUS,
|
||||
&gmode_status);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) ||
|
||||
(profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) {
|
||||
ret = wmax_game_shift_status(priv->wdev,
|
||||
WMAX_OPERATION_TOGGLE_GAME_SHIFT,
|
||||
&gmode_status);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return wmax_thermal_control(priv->wdev,
|
||||
priv->supported_thermal_profiles[profile]);
|
||||
}
|
||||
|
||||
static int thermal_profile_probe(void *drvdata, unsigned long *choices)
|
||||
{
|
||||
enum platform_profile_option profile;
|
||||
struct awcc_priv *priv = drvdata;
|
||||
enum wmax_thermal_mode mode;
|
||||
u8 sys_desc[4];
|
||||
u32 first_mode;
|
||||
u32 out_data;
|
||||
int ret;
|
||||
|
||||
ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_SYS_DESCRIPTION,
|
||||
0, (u32 *) &sys_desc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
first_mode = sys_desc[0] + sys_desc[1];
|
||||
|
||||
for (u32 i = 0; i < sys_desc[3]; i++) {
|
||||
ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_LIST_IDS,
|
||||
i + first_mode, &out_data);
|
||||
|
||||
if (ret == -EIO)
|
||||
return ret;
|
||||
|
||||
if (ret == -EBADRQC)
|
||||
break;
|
||||
|
||||
if (!is_wmax_thermal_code(out_data))
|
||||
continue;
|
||||
|
||||
mode = out_data & WMAX_THERMAL_MODE_MASK;
|
||||
profile = wmax_mode_to_platform_profile[mode];
|
||||
priv->supported_thermal_profiles[profile] = out_data;
|
||||
|
||||
set_bit(profile, choices);
|
||||
}
|
||||
|
||||
if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
|
||||
return -ENODEV;
|
||||
|
||||
if (awcc->gmode) {
|
||||
priv->supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
|
||||
WMAX_THERMAL_MODE_GMODE;
|
||||
|
||||
set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_profile_ops awcc_platform_profile_ops = {
|
||||
.probe = thermal_profile_probe,
|
||||
.profile_get = thermal_profile_get,
|
||||
.profile_set = thermal_profile_set,
|
||||
};
|
||||
|
||||
static int awcc_platform_profile_init(struct wmi_device *wdev)
|
||||
{
|
||||
struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
|
||||
|
||||
priv->ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi",
|
||||
priv, &awcc_platform_profile_ops);
|
||||
|
||||
return PTR_ERR_OR_ZERO(priv->ppdev);
|
||||
}
|
||||
|
||||
static int alienware_awcc_setup(struct wmi_device *wdev)
|
||||
{
|
||||
struct awcc_priv *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->wdev = wdev;
|
||||
dev_set_drvdata(&wdev->dev, priv);
|
||||
|
||||
if (awcc->pprof) {
|
||||
ret = awcc_platform_profile_init(wdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* WMAX WMI driver
|
||||
*/
|
||||
static int wmax_wmi_update_led(struct alienfx_priv *priv,
|
||||
struct wmi_device *wdev, u8 location)
|
||||
{
|
||||
struct wmax_led_args in_args = {
|
||||
.led_mask = 1 << location,
|
||||
.colors = priv->colors[location],
|
||||
.state = priv->lighting_control_state,
|
||||
};
|
||||
|
||||
return alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, &in_args,
|
||||
sizeof(in_args), NULL);
|
||||
}
|
||||
|
||||
static int wmax_wmi_update_brightness(struct alienfx_priv *priv,
|
||||
struct wmi_device *wdev, u8 brightness)
|
||||
{
|
||||
struct wmax_brightness_args in_args = {
|
||||
.led_mask = 0xFF,
|
||||
.percentage = brightness,
|
||||
};
|
||||
|
||||
return alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args,
|
||||
sizeof(in_args), NULL);
|
||||
}
|
||||
|
||||
static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
|
||||
{
|
||||
struct alienfx_platdata pdata = {
|
||||
.wdev = wdev,
|
||||
.ops = {
|
||||
.upd_led = wmax_wmi_update_led,
|
||||
.upd_brightness = wmax_wmi_update_brightness,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (awcc)
|
||||
ret = alienware_awcc_setup(wdev);
|
||||
else
|
||||
ret = alienware_alienfx_setup(&pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct wmi_device_id alienware_wmax_device_id_table[] = {
|
||||
{ WMAX_CONTROL_GUID, NULL },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(wmi, alienware_wmax_device_id_table);
|
||||
|
||||
static struct wmi_driver alienware_wmax_wmi_driver = {
|
||||
.driver = {
|
||||
.name = "alienware-wmi-wmax",
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
},
|
||||
.id_table = alienware_wmax_device_id_table,
|
||||
.probe = wmax_wmi_probe,
|
||||
.no_singleton = true,
|
||||
};
|
||||
|
||||
int __init alienware_wmax_wmi_init(void)
|
||||
{
|
||||
const struct dmi_system_id *id;
|
||||
|
||||
id = dmi_first_match(awcc_dmi_table);
|
||||
if (id)
|
||||
awcc = id->driver_data;
|
||||
|
||||
if (force_platform_profile) {
|
||||
if (!awcc)
|
||||
awcc = &empty_quirks;
|
||||
|
||||
awcc->pprof = true;
|
||||
}
|
||||
|
||||
if (force_gmode) {
|
||||
if (awcc)
|
||||
awcc->gmode = true;
|
||||
else
|
||||
pr_warn("force_gmode requires platform profile support\n");
|
||||
}
|
||||
|
||||
return wmi_driver_register(&alienware_wmax_wmi_driver);
|
||||
}
|
||||
|
||||
void __exit alienware_wmax_wmi_exit(void)
|
||||
{
|
||||
wmi_driver_unregister(&alienware_wmax_wmi_driver);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
117
drivers/platform/x86/dell/alienware-wmi.h
Normal file
117
drivers/platform/x86/dell/alienware-wmi.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Alienware WMI special features driver
|
||||
*
|
||||
* Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com>
|
||||
* Copyright (C) 2024 Kurt Borja <kuurtb@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _ALIENWARE_WMI_H_
|
||||
#define _ALIENWARE_WMI_H_
|
||||
|
||||
#include <linux/leds.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/wmi.h>
|
||||
|
||||
#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492"
|
||||
#define LEGACY_POWER_CONTROL_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
|
||||
#define WMAX_CONTROL_GUID "A70591CE-A997-11DA-B012-B622A1EF5492"
|
||||
|
||||
enum INTERFACE_FLAGS {
|
||||
LEGACY,
|
||||
WMAX,
|
||||
};
|
||||
|
||||
enum LEGACY_CONTROL_STATES {
|
||||
LEGACY_RUNNING = 1,
|
||||
LEGACY_BOOTING = 0,
|
||||
LEGACY_SUSPEND = 3,
|
||||
};
|
||||
|
||||
enum WMAX_CONTROL_STATES {
|
||||
WMAX_RUNNING = 0xFF,
|
||||
WMAX_BOOTING = 0,
|
||||
WMAX_SUSPEND = 3,
|
||||
};
|
||||
|
||||
struct alienfx_quirks {
|
||||
u8 num_zones;
|
||||
bool hdmi_mux;
|
||||
bool amplifier;
|
||||
bool deepslp;
|
||||
};
|
||||
|
||||
struct color_platform {
|
||||
u8 blue;
|
||||
u8 green;
|
||||
u8 red;
|
||||
} __packed;
|
||||
|
||||
struct alienfx_priv {
|
||||
struct platform_device *pdev;
|
||||
struct led_classdev global_led;
|
||||
struct color_platform colors[4];
|
||||
u8 global_brightness;
|
||||
u8 lighting_control_state;
|
||||
};
|
||||
|
||||
struct alienfx_ops {
|
||||
int (*upd_led)(struct alienfx_priv *priv, struct wmi_device *wdev,
|
||||
u8 location);
|
||||
int (*upd_brightness)(struct alienfx_priv *priv, struct wmi_device *wdev,
|
||||
u8 brightness);
|
||||
};
|
||||
|
||||
struct alienfx_platdata {
|
||||
struct wmi_device *wdev;
|
||||
struct alienfx_ops ops;
|
||||
};
|
||||
|
||||
extern u8 alienware_interface;
|
||||
extern struct alienfx_quirks *alienfx;
|
||||
|
||||
int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
|
||||
void *in_args, size_t in_size, u32 *out_data);
|
||||
|
||||
int alienware_alienfx_setup(struct alienfx_platdata *pdata);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ALIENWARE_WMI_LEGACY)
|
||||
int __init alienware_legacy_wmi_init(void);
|
||||
void __exit alienware_legacy_wmi_exit(void);
|
||||
#else
|
||||
static inline int alienware_legacy_wmi_init(void)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void alienware_legacy_wmi_exit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ALIENWARE_WMI_WMAX)
|
||||
extern const struct attribute_group wmax_hdmi_attribute_group;
|
||||
extern const struct attribute_group wmax_amplifier_attribute_group;
|
||||
extern const struct attribute_group wmax_deepsleep_attribute_group;
|
||||
|
||||
#define WMAX_DEV_GROUPS &wmax_hdmi_attribute_group, \
|
||||
&wmax_amplifier_attribute_group, \
|
||||
&wmax_deepsleep_attribute_group,
|
||||
|
||||
int __init alienware_wmax_wmi_init(void);
|
||||
void __exit alienware_wmax_wmi_exit(void);
|
||||
#else
|
||||
#define WMAX_DEV_GROUPS
|
||||
|
||||
static inline int alienware_wmax_wmi_init(void)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static inline void alienware_wmax_wmi_exit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -325,7 +325,7 @@ static int dell_uart_bl_serdev_probe(struct serdev_device *serdev)
|
|||
return PTR_ERR_OR_ZERO(dell_bl->bl);
|
||||
}
|
||||
|
||||
struct serdev_device_driver dell_uart_bl_serdev_driver = {
|
||||
static struct serdev_device_driver dell_uart_bl_serdev_driver = {
|
||||
.probe = dell_uart_bl_serdev_probe,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ struct dell_wmi_ddv_sensors {
|
|||
|
||||
struct dell_wmi_ddv_data {
|
||||
struct acpi_battery_hook hook;
|
||||
struct device_attribute temp_attr;
|
||||
struct device_attribute eppid_attr;
|
||||
struct dell_wmi_ddv_sensors fans;
|
||||
struct dell_wmi_ddv_sensors temps;
|
||||
|
|
@ -651,24 +650,6 @@ static int dell_wmi_ddv_battery_index(struct acpi_device *acpi_dev, u32 *index)
|
|||
return kstrtou32(uid_str, 10, index);
|
||||
}
|
||||
|
||||
static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dell_wmi_ddv_data *data = container_of(attr, struct dell_wmi_ddv_data, temp_attr);
|
||||
u32 index, value;
|
||||
int ret;
|
||||
|
||||
ret = dell_wmi_ddv_battery_index(to_acpi_device(dev->parent), &index);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_TEMPERATURE, index, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Use 2731 instead of 2731.5 to avoid unnecessary rounding */
|
||||
return sysfs_emit(buf, "%d\n", value - 2731);
|
||||
}
|
||||
|
||||
static ssize_t eppid_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dell_wmi_ddv_data *data = container_of(attr, struct dell_wmi_ddv_data, eppid_attr);
|
||||
|
|
@ -695,6 +676,46 @@ static ssize_t eppid_show(struct device *dev, struct device_attribute *attr, cha
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dell_wmi_ddv_get_property(struct power_supply *psy, const struct power_supply_ext *ext,
|
||||
void *drvdata, enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct dell_wmi_ddv_data *data = drvdata;
|
||||
u32 index, value;
|
||||
int ret;
|
||||
|
||||
ret = dell_wmi_ddv_battery_index(to_acpi_device(psy->dev.parent), &index);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_TEMPERATURE, index,
|
||||
&value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Use 2732 instead of 2731.5 to avoid unnecessary rounding and to emulate
|
||||
* the behaviour of the OEM application which seems to round down the result.
|
||||
*/
|
||||
val->intval = value - 2732;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const enum power_supply_property dell_wmi_ddv_properties[] = {
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
};
|
||||
|
||||
static const struct power_supply_ext dell_wmi_ddv_extension = {
|
||||
.name = DRIVER_NAME,
|
||||
.properties = dell_wmi_ddv_properties,
|
||||
.num_properties = ARRAY_SIZE(dell_wmi_ddv_properties),
|
||||
.get_property = dell_wmi_ddv_get_property,
|
||||
};
|
||||
|
||||
static int dell_wmi_ddv_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
|
||||
{
|
||||
struct dell_wmi_ddv_data *data = container_of(hook, struct dell_wmi_ddv_data, hook);
|
||||
|
|
@ -706,13 +727,14 @@ static int dell_wmi_ddv_add_battery(struct power_supply *battery, struct acpi_ba
|
|||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
ret = device_create_file(&battery->dev, &data->temp_attr);
|
||||
ret = device_create_file(&battery->dev, &data->eppid_attr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = device_create_file(&battery->dev, &data->eppid_attr);
|
||||
ret = power_supply_register_extension(battery, &dell_wmi_ddv_extension, &data->wdev->dev,
|
||||
data);
|
||||
if (ret < 0) {
|
||||
device_remove_file(&battery->dev, &data->temp_attr);
|
||||
device_remove_file(&battery->dev, &data->eppid_attr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -724,38 +746,24 @@ static int dell_wmi_ddv_remove_battery(struct power_supply *battery, struct acpi
|
|||
{
|
||||
struct dell_wmi_ddv_data *data = container_of(hook, struct dell_wmi_ddv_data, hook);
|
||||
|
||||
device_remove_file(&battery->dev, &data->temp_attr);
|
||||
device_remove_file(&battery->dev, &data->eppid_attr);
|
||||
power_supply_unregister_extension(battery, &dell_wmi_ddv_extension);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dell_wmi_ddv_battery_remove(void *data)
|
||||
{
|
||||
struct acpi_battery_hook *hook = data;
|
||||
|
||||
battery_hook_unregister(hook);
|
||||
}
|
||||
|
||||
static int dell_wmi_ddv_battery_add(struct dell_wmi_ddv_data *data)
|
||||
{
|
||||
data->hook.name = "Dell DDV Battery Extension";
|
||||
data->hook.add_battery = dell_wmi_ddv_add_battery;
|
||||
data->hook.remove_battery = dell_wmi_ddv_remove_battery;
|
||||
|
||||
sysfs_attr_init(&data->temp_attr.attr);
|
||||
data->temp_attr.attr.name = "temp";
|
||||
data->temp_attr.attr.mode = 0444;
|
||||
data->temp_attr.show = temp_show;
|
||||
|
||||
sysfs_attr_init(&data->eppid_attr.attr);
|
||||
data->eppid_attr.attr.name = "eppid";
|
||||
data->eppid_attr.attr.mode = 0444;
|
||||
data->eppid_attr.show = eppid_show;
|
||||
|
||||
battery_hook_register(&data->hook);
|
||||
|
||||
return devm_add_action_or_reset(&data->wdev->dev, dell_wmi_ddv_battery_remove, &data->hook);
|
||||
return devm_battery_hook_register(&data->wdev->dev, &data->hook);
|
||||
}
|
||||
|
||||
static int dell_wmi_ddv_buffer_read(struct seq_file *seq, enum dell_ddv_method method)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman.o
|
||||
dell-wmi-sysman-objs := sysman.o \
|
||||
dell-wmi-sysman-y := sysman.o \
|
||||
enum-attributes.o \
|
||||
int-attributes.o \
|
||||
string-attributes.o \
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
obj-$(CONFIG_HP_BIOSCFG) := hp-bioscfg.o
|
||||
|
||||
hp-bioscfg-objs := bioscfg.o \
|
||||
hp-bioscfg-y := bioscfg.o \
|
||||
biosattr-interface.o \
|
||||
enum-attributes.o \
|
||||
int-attributes.o \
|
||||
|
|
|
|||
|
|
@ -388,16 +388,13 @@ union acpi_object *hp_get_wmiobj_pointer(int instance_id, const char *guid_strin
|
|||
*/
|
||||
int hp_get_instance_count(const char *guid_string)
|
||||
{
|
||||
union acpi_object *wmi_obj = NULL;
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
kfree(wmi_obj);
|
||||
wmi_obj = hp_get_wmiobj_pointer(i, guid_string);
|
||||
i++;
|
||||
} while (wmi_obj);
|
||||
ret = wmi_instance_count(guid_string);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
return i - 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -448,7 +445,7 @@ int hp_convert_hexstr_to_str(const char *input, u32 input_len, char **str, int *
|
|||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < input_len; i += 5) {
|
||||
strncpy(tmp, input + i, strlen(tmp));
|
||||
strscpy(tmp, input + i);
|
||||
if (kstrtol(tmp, 16, &ch) == 0) {
|
||||
// escape char
|
||||
if (ch == '\\' ||
|
||||
|
|
|
|||
|
|
@ -854,6 +854,7 @@ static const struct attribute_group ideapad_attribute_group = {
|
|||
.is_visible = ideapad_is_visible,
|
||||
.attrs = ideapad_attributes
|
||||
};
|
||||
__ATTRIBUTE_GROUPS(ideapad_attribute);
|
||||
|
||||
/*
|
||||
* DYTC Platform profile
|
||||
|
|
@ -1244,21 +1245,6 @@ static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
|
|||
rfkill_destroy(priv->rfk[dev]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Platform device
|
||||
*/
|
||||
static int ideapad_sysfs_init(struct ideapad_private *priv)
|
||||
{
|
||||
return device_add_group(&priv->platform_device->dev,
|
||||
&ideapad_attribute_group);
|
||||
}
|
||||
|
||||
static void ideapad_sysfs_exit(struct ideapad_private *priv)
|
||||
{
|
||||
device_remove_group(&priv->platform_device->dev,
|
||||
&ideapad_attribute_group);
|
||||
}
|
||||
|
||||
/*
|
||||
* input device
|
||||
*/
|
||||
|
|
@ -2175,10 +2161,6 @@ static int ideapad_acpi_add(struct platform_device *pdev)
|
|||
|
||||
ideapad_check_features(priv);
|
||||
|
||||
err = ideapad_sysfs_init(priv);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ideapad_debugfs_init(priv);
|
||||
|
||||
err = ideapad_input_init(priv);
|
||||
|
|
@ -2265,7 +2247,6 @@ static int ideapad_acpi_add(struct platform_device *pdev)
|
|||
|
||||
input_failed:
|
||||
ideapad_debugfs_exit(priv);
|
||||
ideapad_sysfs_exit(priv);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -2293,7 +2274,6 @@ static void ideapad_acpi_remove(struct platform_device *pdev)
|
|||
ideapad_kbd_bl_exit(priv);
|
||||
ideapad_input_exit(priv);
|
||||
ideapad_debugfs_exit(priv);
|
||||
ideapad_sysfs_exit(priv);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
@ -2325,6 +2305,7 @@ static struct platform_driver ideapad_acpi_driver = {
|
|||
.name = "ideapad_acpi",
|
||||
.pm = &ideapad_pm,
|
||||
.acpi_match_table = ACPI_PTR(ideapad_device_ids),
|
||||
.dev_groups = ideapad_attribute_groups,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
obj-$(CONFIG_INTEL_IFS) += intel_ifs.o
|
||||
|
||||
intel_ifs-objs := core.o load.o runtest.o sysfs.o
|
||||
intel_ifs-y := core.o load.o runtest.o sysfs.o
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *i
|
|||
|
||||
static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry,
|
||||
struct acpi_resource_gpio *agpio,
|
||||
const char *func, unsigned long gpio_flags)
|
||||
const char *con_id, unsigned long gpio_flags)
|
||||
{
|
||||
char *path = agpio->resource_source.string_ptr;
|
||||
struct acpi_device *adev;
|
||||
|
|
@ -71,14 +71,14 @@ static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry,
|
|||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
*table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], func, gpio_flags);
|
||||
*table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], con_id, gpio_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472,
|
||||
struct acpi_resource_gpio *agpio,
|
||||
const char *func, unsigned long gpio_flags)
|
||||
const char *con_id, unsigned long gpio_flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347
|
|||
}
|
||||
|
||||
ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios],
|
||||
agpio, func, gpio_flags);
|
||||
agpio, con_id, gpio_flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347
|
|||
static struct gpio_desc *
|
||||
skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
|
||||
struct acpi_resource_gpio *agpio,
|
||||
const char *func, unsigned long gpio_flags)
|
||||
const char *con_id, unsigned long gpio_flags)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
int ret;
|
||||
|
|
@ -112,12 +112,12 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
lookup->dev_id = dev_name(int3472->dev);
|
||||
ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, func, gpio_flags);
|
||||
ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, con_id, gpio_flags);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
gpiod_add_lookup_table(lookup);
|
||||
desc = devm_gpiod_get(int3472->dev, func, GPIOD_OUT_LOW);
|
||||
desc = devm_gpiod_get(int3472->dev, con_id, GPIOD_OUT_LOW);
|
||||
gpiod_remove_lookup_table(lookup);
|
||||
|
||||
return desc;
|
||||
|
|
@ -129,7 +129,7 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
|
|||
* @hid: The ACPI HID of the device without the instance number e.g. INT347E
|
||||
* @type_from: The GPIO type from ACPI ?SDT
|
||||
* @type_to: The assigned GPIO type, typically same as @type_from
|
||||
* @func: The function, e.g. "enable"
|
||||
* @con_id: The name of the GPIO for the device
|
||||
* @polarity_low: GPIO_ACTIVE_LOW true if the @polarity_low is true,
|
||||
* GPIO_ACTIVE_HIGH otherwise
|
||||
*/
|
||||
|
|
@ -138,15 +138,15 @@ struct int3472_gpio_map {
|
|||
u8 type_from;
|
||||
u8 type_to;
|
||||
bool polarity_low;
|
||||
const char *func;
|
||||
const char *con_id;
|
||||
};
|
||||
|
||||
static const struct int3472_gpio_map int3472_gpio_map[] = {
|
||||
{ "INT347E", INT3472_GPIO_TYPE_RESET, INT3472_GPIO_TYPE_RESET, false, "enable" },
|
||||
};
|
||||
|
||||
static void int3472_get_func_and_polarity(struct acpi_device *adev, u8 *type,
|
||||
const char **func, unsigned long *gpio_flags)
|
||||
static void int3472_get_con_id_and_polarity(struct acpi_device *adev, u8 *type,
|
||||
const char **con_id, unsigned long *gpio_flags)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
|
@ -165,33 +165,33 @@ static void int3472_get_func_and_polarity(struct acpi_device *adev, u8 *type,
|
|||
*type = int3472_gpio_map[i].type_to;
|
||||
*gpio_flags = int3472_gpio_map[i].polarity_low ?
|
||||
GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH;
|
||||
*func = int3472_gpio_map[i].func;
|
||||
*con_id = int3472_gpio_map[i].con_id;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (*type) {
|
||||
case INT3472_GPIO_TYPE_RESET:
|
||||
*func = "reset";
|
||||
*con_id = "reset";
|
||||
*gpio_flags = GPIO_ACTIVE_LOW;
|
||||
break;
|
||||
case INT3472_GPIO_TYPE_POWERDOWN:
|
||||
*func = "powerdown";
|
||||
*con_id = "powerdown";
|
||||
*gpio_flags = GPIO_ACTIVE_LOW;
|
||||
break;
|
||||
case INT3472_GPIO_TYPE_CLK_ENABLE:
|
||||
*func = "clk-enable";
|
||||
*con_id = "clk-enable";
|
||||
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||
break;
|
||||
case INT3472_GPIO_TYPE_PRIVACY_LED:
|
||||
*func = "privacy-led";
|
||||
*con_id = "privacy-led";
|
||||
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||
break;
|
||||
case INT3472_GPIO_TYPE_POWER_ENABLE:
|
||||
*func = "power-enable";
|
||||
*con_id = "power-enable";
|
||||
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||
break;
|
||||
default:
|
||||
*func = "unknown";
|
||||
*con_id = "unknown";
|
||||
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||
break;
|
||||
}
|
||||
|
|
@ -238,7 +238,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
|
|||
union acpi_object *obj;
|
||||
struct gpio_desc *gpio;
|
||||
const char *err_msg;
|
||||
const char *func;
|
||||
const char *con_id;
|
||||
unsigned long gpio_flags;
|
||||
int ret;
|
||||
|
||||
|
|
@ -262,26 +262,26 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
|
|||
|
||||
type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value);
|
||||
|
||||
int3472_get_func_and_polarity(int3472->sensor, &type, &func, &gpio_flags);
|
||||
int3472_get_con_id_and_polarity(int3472->sensor, &type, &con_id, &gpio_flags);
|
||||
|
||||
pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value);
|
||||
/* Pin field is not really used under Windows and wraps around at 8 bits */
|
||||
if (pin != (agpio->pin_table[0] & 0xff))
|
||||
dev_dbg(int3472->dev, FW_BUG "%s %s pin number mismatch _DSM %d resource %d\n",
|
||||
func, agpio->resource_source.string_ptr, pin, agpio->pin_table[0]);
|
||||
con_id, agpio->resource_source.string_ptr, pin, agpio->pin_table[0]);
|
||||
|
||||
active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value);
|
||||
if (!active_value)
|
||||
gpio_flags ^= GPIO_ACTIVE_LOW;
|
||||
|
||||
dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func,
|
||||
dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", con_id,
|
||||
agpio->resource_source.string_ptr, agpio->pin_table[0],
|
||||
str_high_low(gpio_flags == GPIO_ACTIVE_HIGH));
|
||||
|
||||
switch (type) {
|
||||
case INT3472_GPIO_TYPE_RESET:
|
||||
case INT3472_GPIO_TYPE_POWERDOWN:
|
||||
ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, func, gpio_flags);
|
||||
ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, con_id, gpio_flags);
|
||||
if (ret)
|
||||
err_msg = "Failed to map GPIO pin to sensor\n";
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
|
|||
case INT3472_GPIO_TYPE_CLK_ENABLE:
|
||||
case INT3472_GPIO_TYPE_PRIVACY_LED:
|
||||
case INT3472_GPIO_TYPE_POWER_ENABLE:
|
||||
gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, func, gpio_flags);
|
||||
gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, con_id, gpio_flags);
|
||||
if (IS_ERR(gpio)) {
|
||||
ret = PTR_ERR(gpio);
|
||||
err_msg = "Failed to get GPIO\n";
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
|
||||
intel_pmc_core-y := core.o core_ssram.o spt.o cnp.o \
|
||||
icl.o tgl.o adl.o mtl.o arl.o lnl.o
|
||||
icl.o tgl.o adl.o mtl.o arl.o lnl.o ptl.o
|
||||
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
|
||||
intel_pmc_core_pltdrv-y := pltdrv.o
|
||||
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include "core.h"
|
||||
|
||||
/* Alder Lake: PGD PFET Enable Ack Status Register(s) bitmap */
|
||||
const struct pmc_bit_map adl_pfear_map[] = {
|
||||
static const struct pmc_bit_map adl_pfear_map[] = {
|
||||
{"SPI/eSPI", BIT(2)},
|
||||
{"XHCI", BIT(3)},
|
||||
{"SPA", BIT(4)},
|
||||
|
|
@ -54,7 +54,7 @@ const struct pmc_bit_map adl_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_adl_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_adl_pfear_map[] = {
|
||||
/*
|
||||
* Check intel_pmc_core_ids[] users of cnp_reg_map for
|
||||
* a list of core SoCs using this.
|
||||
|
|
@ -63,7 +63,7 @@ const struct pmc_bit_map *ext_adl_pfear_map[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_ltr_show_map[] = {
|
||||
static const struct pmc_bit_map adl_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
|
||||
{"SATA", CNP_PMC_LTR_SATA},
|
||||
|
|
@ -100,7 +100,7 @@ const struct pmc_bit_map adl_ltr_show_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_clocksource_status_map[] = {
|
||||
static const struct pmc_bit_map adl_clocksource_status_map[] = {
|
||||
{"CLKPART1_OFF_STS", BIT(0)},
|
||||
{"CLKPART2_OFF_STS", BIT(1)},
|
||||
{"CLKPART3_OFF_STS", BIT(2)},
|
||||
|
|
@ -128,7 +128,7 @@ const struct pmc_bit_map adl_clocksource_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_power_gating_status_0_map[] = {
|
||||
static const struct pmc_bit_map adl_power_gating_status_0_map[] = {
|
||||
{"PMC_PGD0_PG_STS", BIT(0)},
|
||||
{"DMI_PGD0_PG_STS", BIT(1)},
|
||||
{"ESPISPI_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -158,7 +158,7 @@ const struct pmc_bit_map adl_power_gating_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_power_gating_status_1_map[] = {
|
||||
static const struct pmc_bit_map adl_power_gating_status_1_map[] = {
|
||||
{"USBR0_PGD0_PG_STS", BIT(0)},
|
||||
{"SMT1_PGD0_PG_STS", BIT(2)},
|
||||
{"CSMERTC_PGD0_PG_STS", BIT(6)},
|
||||
|
|
@ -170,14 +170,14 @@ const struct pmc_bit_map adl_power_gating_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_power_gating_status_2_map[] = {
|
||||
static const struct pmc_bit_map adl_power_gating_status_2_map[] = {
|
||||
{"THC0_PGD0_PG_STS", BIT(7)},
|
||||
{"THC1_PGD0_PG_STS", BIT(8)},
|
||||
{"SPF_PGD0_PG_STS", BIT(14)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_d3_status_0_map[] = {
|
||||
static const struct pmc_bit_map adl_d3_status_0_map[] = {
|
||||
{"ISH_D3_STS", BIT(2)},
|
||||
{"LPSS_D3_STS", BIT(3)},
|
||||
{"XDCI_D3_STS", BIT(4)},
|
||||
|
|
@ -193,13 +193,13 @@ const struct pmc_bit_map adl_d3_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_d3_status_1_map[] = {
|
||||
static const struct pmc_bit_map adl_d3_status_1_map[] = {
|
||||
{"GBE_D3_STS", BIT(19)},
|
||||
{"CNVI_D3_STS", BIT(27)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_d3_status_2_map[] = {
|
||||
static const struct pmc_bit_map adl_d3_status_2_map[] = {
|
||||
{"CSMERTC_D3_STS", BIT(1)},
|
||||
{"CSE_D3_STS", BIT(4)},
|
||||
{"KVMCC_D3_STS", BIT(5)},
|
||||
|
|
@ -210,20 +210,20 @@ const struct pmc_bit_map adl_d3_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_d3_status_3_map[] = {
|
||||
static const struct pmc_bit_map adl_d3_status_3_map[] = {
|
||||
{"THC0_D3_STS", BIT(14)},
|
||||
{"THC1_D3_STS", BIT(15)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_vnn_req_status_0_map[] = {
|
||||
static const struct pmc_bit_map adl_vnn_req_status_0_map[] = {
|
||||
{"ISH_VNN_REQ_STS", BIT(2)},
|
||||
{"ESPISPI_VNN_REQ_STS", BIT(18)},
|
||||
{"DSP_VNN_REQ_STS", BIT(19)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_vnn_req_status_1_map[] = {
|
||||
static const struct pmc_bit_map adl_vnn_req_status_1_map[] = {
|
||||
{"NPK_VNN_REQ_STS", BIT(4)},
|
||||
{"EXI_VNN_REQ_STS", BIT(9)},
|
||||
{"GBE_VNN_REQ_STS", BIT(19)},
|
||||
|
|
@ -232,7 +232,7 @@ const struct pmc_bit_map adl_vnn_req_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_vnn_req_status_2_map[] = {
|
||||
static const struct pmc_bit_map adl_vnn_req_status_2_map[] = {
|
||||
{"CSMERTC_VNN_REQ_STS", BIT(1)},
|
||||
{"CSE_VNN_REQ_STS", BIT(4)},
|
||||
{"SMT1_VNN_REQ_STS", BIT(8)},
|
||||
|
|
@ -245,12 +245,12 @@ const struct pmc_bit_map adl_vnn_req_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_vnn_req_status_3_map[] = {
|
||||
static const struct pmc_bit_map adl_vnn_req_status_3_map[] = {
|
||||
{"GPIOCOM5_VNN_REQ_STS", BIT(11)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map adl_vnn_misc_status_map[] = {
|
||||
static const struct pmc_bit_map adl_vnn_misc_status_map[] = {
|
||||
{"CPU_C10_REQ_STS", BIT(0)},
|
||||
{"PCIe_LPM_En_REQ_STS", BIT(3)},
|
||||
{"ITH_REQ_STS", BIT(5)},
|
||||
|
|
@ -265,7 +265,7 @@ const struct pmc_bit_map adl_vnn_misc_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *adl_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *adl_lpm_maps[] = {
|
||||
adl_clocksource_status_map,
|
||||
adl_power_gating_status_0_map,
|
||||
adl_power_gating_status_1_map,
|
||||
|
|
@ -311,20 +311,8 @@ const struct pmc_reg_map adl_reg_map = {
|
|||
.pson_residency_counter_step = TGL_PSON_RES_COUNTER_STEP,
|
||||
};
|
||||
|
||||
int adl_core_init(struct pmc_dev *pmcdev)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
|
||||
int ret;
|
||||
|
||||
pmcdev->suspend = cnl_suspend;
|
||||
pmcdev->resume = cnl_resume;
|
||||
|
||||
pmc->map = &adl_reg_map;
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
struct pmc_dev_info adl_pmc_dev = {
|
||||
.map = &adl_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = cnl_resume,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@
|
|||
#define IOEP_LPM_REQ_GUID 0x5077612
|
||||
#define SOCS_LPM_REQ_GUID 0x8478657
|
||||
#define PCHS_LPM_REQ_GUID 0x9684572
|
||||
#define SOCM_LPM_REQ_GUID 0x2625030
|
||||
|
||||
static const u8 ARL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
|
||||
|
||||
const struct pmc_bit_map arl_socs_ltr_show_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
|
||||
{"SATA", CNP_PMC_LTR_SATA},
|
||||
|
|
@ -59,7 +60,7 @@ const struct pmc_bit_map arl_socs_ltr_show_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_clocksource_status_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_clocksource_status_map[] = {
|
||||
{"AON2_OFF_STS", BIT(0)},
|
||||
{"AON3_OFF_STS", BIT(1)},
|
||||
{"AON4_OFF_STS", BIT(2)},
|
||||
|
|
@ -87,7 +88,7 @@ const struct pmc_bit_map arl_socs_clocksource_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_power_gating_status_0_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_power_gating_status_0_map[] = {
|
||||
{"PMC_PGD0_PG_STS", BIT(0)},
|
||||
{"DMI_PGD0_PG_STS", BIT(1)},
|
||||
{"ESPISPI_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -123,7 +124,7 @@ const struct pmc_bit_map arl_socs_power_gating_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_power_gating_status_1_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_power_gating_status_1_map[] = {
|
||||
{"USBR0_PGD0_PG_STS", BIT(0)},
|
||||
{"SUSRAM_PGD0_PG_STS", BIT(1)},
|
||||
{"SMT1_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -159,7 +160,7 @@ const struct pmc_bit_map arl_socs_power_gating_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_power_gating_status_2_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_power_gating_status_2_map[] = {
|
||||
{"PSF8_PGD0_PG_STS", BIT(0)},
|
||||
{"FIA_PGD0_PG_STS", BIT(1)},
|
||||
{"SOC_D2D_PGD3_PG_STS", BIT(2)},
|
||||
|
|
@ -187,7 +188,7 @@ const struct pmc_bit_map arl_socs_power_gating_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_d3_status_2_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_d3_status_2_map[] = {
|
||||
{"CSMERTC_D3_STS", BIT(1)},
|
||||
{"SUSRAM_D3_STS", BIT(2)},
|
||||
{"CSE_D3_STS", BIT(4)},
|
||||
|
|
@ -206,7 +207,7 @@ const struct pmc_bit_map arl_socs_d3_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_d3_status_3_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_d3_status_3_map[] = {
|
||||
{"GBETSN_D3_STS", BIT(13)},
|
||||
{"THC0_D3_STS", BIT(14)},
|
||||
{"THC1_D3_STS", BIT(15)},
|
||||
|
|
@ -214,13 +215,13 @@ const struct pmc_bit_map arl_socs_d3_status_3_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_vnn_req_status_3_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_vnn_req_status_3_map[] = {
|
||||
{"DTS0_VNN_REQ_STS", BIT(7)},
|
||||
{"GPIOCOM5_VNN_REQ_STS", BIT(11)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *arl_socs_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *arl_socs_lpm_maps[] = {
|
||||
arl_socs_clocksource_status_map,
|
||||
arl_socs_power_gating_status_0_map,
|
||||
arl_socs_power_gating_status_1_map,
|
||||
|
|
@ -238,7 +239,7 @@ const struct pmc_bit_map *arl_socs_lpm_maps[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_socs_pfear_map[] = {
|
||||
static const struct pmc_bit_map arl_socs_pfear_map[] = {
|
||||
{"RSVD64", BIT(0)},
|
||||
{"RSVD65", BIT(1)},
|
||||
{"RSVD66", BIT(2)},
|
||||
|
|
@ -249,13 +250,13 @@ const struct pmc_bit_map arl_socs_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_arl_socs_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_arl_socs_pfear_map[] = {
|
||||
mtl_socm_pfear_map,
|
||||
arl_socs_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_reg_map arl_socs_reg_map = {
|
||||
static const struct pmc_reg_map arl_socs_reg_map = {
|
||||
.pfear_sts = ext_arl_socs_pfear_map,
|
||||
.ppfear_buckets = ARL_SOCS_PPFEAR_NUM_ENTRIES,
|
||||
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
|
||||
|
|
@ -283,7 +284,7 @@ const struct pmc_reg_map arl_socs_reg_map = {
|
|||
.pson_residency_counter_step = TGL_PSON_RES_COUNTER_STEP,
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_ltr_show_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
|
||||
{"SATA", CNP_PMC_LTR_SATA},
|
||||
|
|
@ -323,7 +324,7 @@ const struct pmc_bit_map arl_pchs_ltr_show_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_clocksource_status_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_clocksource_status_map[] = {
|
||||
{"AON2_OFF_STS", BIT(0)},
|
||||
{"AON3_OFF_STS", BIT(1)},
|
||||
{"AON4_OFF_STS", BIT(2)},
|
||||
|
|
@ -358,7 +359,7 @@ const struct pmc_bit_map arl_pchs_clocksource_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_power_gating_status_0_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_power_gating_status_0_map[] = {
|
||||
{"PMC_PGD0_PG_STS", BIT(0)},
|
||||
{"DMI_PGD0_PG_STS", BIT(1)},
|
||||
{"ESPISPI_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -394,7 +395,7 @@ const struct pmc_bit_map arl_pchs_power_gating_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_power_gating_status_1_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_power_gating_status_1_map[] = {
|
||||
{"USBR0_PGD0_PG_STS", BIT(0)},
|
||||
{"SUSRAM_PGD0_PG_STS", BIT(1)},
|
||||
{"SMT1_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -430,7 +431,7 @@ const struct pmc_bit_map arl_pchs_power_gating_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_power_gating_status_2_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_power_gating_status_2_map[] = {
|
||||
{"U3FPW2_PGD0_PG_STS", BIT(0)},
|
||||
{"FIA_PGD0_PG_STS", BIT(1)},
|
||||
{"FIACPCB_X_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -457,7 +458,7 @@ const struct pmc_bit_map arl_pchs_power_gating_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_d3_status_0_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_d3_status_0_map[] = {
|
||||
{"SPF_D3_STS", BIT(0)},
|
||||
{"LPSS_D3_STS", BIT(3)},
|
||||
{"XDCI_D3_STS", BIT(4)},
|
||||
|
|
@ -474,7 +475,7 @@ const struct pmc_bit_map arl_pchs_d3_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_d3_status_1_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_d3_status_1_map[] = {
|
||||
{"GBETSN1_D3_STS", BIT(14)},
|
||||
{"GBE_D3_STS", BIT(19)},
|
||||
{"ITSS_D3_STS", BIT(23)},
|
||||
|
|
@ -483,7 +484,7 @@ const struct pmc_bit_map arl_pchs_d3_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_d3_status_2_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_d3_status_2_map[] = {
|
||||
{"CSMERTC_D3_STS", BIT(1)},
|
||||
{"SUSRAM_D3_STS", BIT(2)},
|
||||
{"CSE_D3_STS", BIT(4)},
|
||||
|
|
@ -504,7 +505,7 @@ const struct pmc_bit_map arl_pchs_d3_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_d3_status_3_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_d3_status_3_map[] = {
|
||||
{"ESE_D3_STS", BIT(3)},
|
||||
{"GBETSN_D3_STS", BIT(13)},
|
||||
{"THC0_D3_STS", BIT(14)},
|
||||
|
|
@ -513,13 +514,13 @@ const struct pmc_bit_map arl_pchs_d3_status_3_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_vnn_req_status_0_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_vnn_req_status_0_map[] = {
|
||||
{"FIA_VNN_REQ_STS", BIT(17)},
|
||||
{"ESPISPI_VNN_REQ_STS", BIT(18)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[] = {
|
||||
{"NPK_VNN_REQ_STS", BIT(4)},
|
||||
{"DFXAGG_VNN_REQ_STS", BIT(8)},
|
||||
{"EXI_VNN_REQ_STS", BIT(9)},
|
||||
|
|
@ -530,7 +531,7 @@ const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[] = {
|
||||
{"FIA2_VNN_REQ_STS", BIT(0)},
|
||||
{"CSMERTC_VNN_REQ_STS", BIT(1)},
|
||||
{"CSE_VNN_REQ_STS", BIT(4)},
|
||||
|
|
@ -548,7 +549,7 @@ const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[] = {
|
||||
{"ESE_VNN_REQ_STS", BIT(3)},
|
||||
{"DTS0_VNN_REQ_STS", BIT(7)},
|
||||
{"GPIOCOM5_VNN_REQ_STS", BIT(11)},
|
||||
|
|
@ -556,7 +557,7 @@ const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_vnn_misc_status_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_vnn_misc_status_map[] = {
|
||||
{"CPU_C10_REQ_STS", BIT(0)},
|
||||
{"TS_OFF_REQ_STS", BIT(1)},
|
||||
{"PNDE_MET_REQ_STS", BIT(2)},
|
||||
|
|
@ -586,7 +587,7 @@ const struct pmc_bit_map arl_pchs_vnn_misc_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map arl_pchs_signal_status_map[] = {
|
||||
static const struct pmc_bit_map arl_pchs_signal_status_map[] = {
|
||||
{"LSX_Wake0_STS", BIT(0)},
|
||||
{"LSX_Wake1_STS", BIT(1)},
|
||||
{"LSX_Wake2_STS", BIT(2)},
|
||||
|
|
@ -606,7 +607,7 @@ const struct pmc_bit_map arl_pchs_signal_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *arl_pchs_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *arl_pchs_lpm_maps[] = {
|
||||
arl_pchs_clocksource_status_map,
|
||||
arl_pchs_power_gating_status_0_map,
|
||||
arl_pchs_power_gating_status_1_map,
|
||||
|
|
@ -624,7 +625,7 @@ const struct pmc_bit_map *arl_pchs_lpm_maps[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_reg_map arl_pchs_reg_map = {
|
||||
static const struct pmc_reg_map arl_pchs_reg_map = {
|
||||
.pfear_sts = ext_arl_socs_pfear_map,
|
||||
.ppfear_buckets = ARL_SOCS_PPFEAR_NUM_ENTRIES,
|
||||
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
|
||||
|
|
@ -650,6 +651,7 @@ const struct pmc_reg_map arl_pchs_reg_map = {
|
|||
.etr3_offset = ETR3_OFFSET,
|
||||
};
|
||||
|
||||
#define PMC_DEVID_SOCM 0x777f
|
||||
#define PMC_DEVID_SOCS 0xae7f
|
||||
#define PMC_DEVID_IOEP 0x7ecf
|
||||
#define PMC_DEVID_PCHS 0x7f27
|
||||
|
|
@ -669,11 +671,17 @@ static struct pmc_info arl_pmc_info_list[] = {
|
|||
.devid = PMC_DEVID_PCHS,
|
||||
.map = &arl_pchs_reg_map,
|
||||
},
|
||||
{
|
||||
.guid = SOCM_LPM_REQ_GUID,
|
||||
.devid = PMC_DEVID_SOCM,
|
||||
.map = &mtl_socm_reg_map,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
#define ARL_NPU_PCI_DEV 0xad1d
|
||||
#define ARL_GNA_PCI_DEV 0xae4c
|
||||
#define ARL_H_GNA_PCI_DEV 0x774c
|
||||
/*
|
||||
* Set power state of select devices that do not have drivers to D3
|
||||
* so that they do not block Package C entry.
|
||||
|
|
@ -684,6 +692,12 @@ static void arl_d3_fixup(void)
|
|||
pmc_core_set_device_d3(ARL_GNA_PCI_DEV);
|
||||
}
|
||||
|
||||
static void arl_h_d3_fixup(void)
|
||||
{
|
||||
pmc_core_set_device_d3(ARL_NPU_PCI_DEV);
|
||||
pmc_core_set_device_d3(ARL_H_GNA_PCI_DEV);
|
||||
}
|
||||
|
||||
static int arl_resume(struct pmc_dev *pmcdev)
|
||||
{
|
||||
arl_d3_fixup();
|
||||
|
|
@ -691,40 +705,41 @@ static int arl_resume(struct pmc_dev *pmcdev)
|
|||
return cnl_resume(pmcdev);
|
||||
}
|
||||
|
||||
int arl_core_init(struct pmc_dev *pmcdev)
|
||||
static int arl_h_resume(struct pmc_dev *pmcdev)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
|
||||
int ret;
|
||||
int func = 0;
|
||||
bool ssram_init = true;
|
||||
arl_h_d3_fixup();
|
||||
|
||||
arl_d3_fixup();
|
||||
pmcdev->suspend = cnl_suspend;
|
||||
pmcdev->resume = arl_resume;
|
||||
pmcdev->regmap_list = arl_pmc_info_list;
|
||||
|
||||
/*
|
||||
* If ssram init fails use legacy method to at least get the
|
||||
* primary PMC
|
||||
*/
|
||||
ret = pmc_core_ssram_init(pmcdev, func);
|
||||
if (ret) {
|
||||
ssram_init = false;
|
||||
pmc->map = &arl_socs_reg_map;
|
||||
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
pmc_core_punit_pmt_init(pmcdev, ARL_PMT_DMU_GUID);
|
||||
|
||||
if (ssram_init) {
|
||||
ret = pmc_core_ssram_get_lpm_reqs(pmcdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return cnl_resume(pmcdev);
|
||||
}
|
||||
|
||||
static int arl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
arl_d3_fixup();
|
||||
return generic_core_init(pmcdev, pmc_dev_info);
|
||||
}
|
||||
|
||||
static int arl_h_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
arl_h_d3_fixup();
|
||||
return generic_core_init(pmcdev, pmc_dev_info);
|
||||
}
|
||||
|
||||
struct pmc_dev_info arl_pmc_dev = {
|
||||
.pci_func = 0,
|
||||
.dmu_guid = ARL_PMT_DMU_GUID,
|
||||
.regmap_list = arl_pmc_info_list,
|
||||
.map = &arl_socs_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = arl_resume,
|
||||
.init = arl_core_init,
|
||||
};
|
||||
|
||||
struct pmc_dev_info arl_h_pmc_dev = {
|
||||
.pci_func = 2,
|
||||
.dmu_guid = ARL_PMT_DMU_GUID,
|
||||
.regmap_list = arl_pmc_info_list,
|
||||
.map = &mtl_socm_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = arl_h_resume,
|
||||
.init = arl_h_core_init,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ const struct pmc_bit_map cnp_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_cnp_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_cnp_pfear_map[] = {
|
||||
/*
|
||||
* Check intel_pmc_core_ids[] users of cnp_reg_map for
|
||||
* a list of core SoCs using this.
|
||||
|
|
@ -97,7 +97,7 @@ const struct pmc_bit_map *ext_cnp_pfear_map[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map cnp_slps0_dbg0_map[] = {
|
||||
static const struct pmc_bit_map cnp_slps0_dbg0_map[] = {
|
||||
{"AUDIO_D3", BIT(0)},
|
||||
{"OTG_D3", BIT(1)},
|
||||
{"XHCI_D3", BIT(2)},
|
||||
|
|
@ -110,7 +110,7 @@ const struct pmc_bit_map cnp_slps0_dbg0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map cnp_slps0_dbg1_map[] = {
|
||||
static const struct pmc_bit_map cnp_slps0_dbg1_map[] = {
|
||||
{"SDIO_PLL_OFF", BIT(0)},
|
||||
{"USB2_PLL_OFF", BIT(1)},
|
||||
{"AUDIO_PLL_OFF", BIT(2)},
|
||||
|
|
@ -127,7 +127,7 @@ const struct pmc_bit_map cnp_slps0_dbg1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map cnp_slps0_dbg2_map[] = {
|
||||
static const struct pmc_bit_map cnp_slps0_dbg2_map[] = {
|
||||
{"MPHY_CORE_GATED", BIT(0)},
|
||||
{"CSME_GATED", BIT(1)},
|
||||
{"USB2_SUS_GATED", BIT(2)},
|
||||
|
|
@ -274,20 +274,9 @@ int cnl_resume(struct pmc_dev *pmcdev)
|
|||
return pmc_core_resume_common(pmcdev);
|
||||
}
|
||||
|
||||
int cnp_core_init(struct pmc_dev *pmcdev)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
|
||||
int ret;
|
||||
struct pmc_dev_info cnp_pmc_dev = {
|
||||
.map = &cnp_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = cnl_resume,
|
||||
};
|
||||
|
||||
pmcdev->suspend = cnl_suspend;
|
||||
pmcdev->resume = cnl_resume;
|
||||
|
||||
pmc->map = &cnp_reg_map;
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1345,40 +1345,80 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When supported, ssram init is used to achieve all available PMCs.
|
||||
* If ssram init fails, this function uses legacy method to at least get the
|
||||
* primary PMC.
|
||||
*/
|
||||
int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
|
||||
bool ssram;
|
||||
int ret;
|
||||
|
||||
pmcdev->suspend = pmc_dev_info->suspend;
|
||||
pmcdev->resume = pmc_dev_info->resume;
|
||||
|
||||
ssram = pmc_dev_info->regmap_list != NULL;
|
||||
if (ssram) {
|
||||
pmcdev->regmap_list = pmc_dev_info->regmap_list;
|
||||
ret = pmc_core_ssram_init(pmcdev, pmc_dev_info->pci_func);
|
||||
if (ret) {
|
||||
dev_warn(&pmcdev->pdev->dev,
|
||||
"ssram init failed, %d, using legacy init\n", ret);
|
||||
ssram = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ssram) {
|
||||
pmc->map = pmc_dev_info->map;
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
if (pmc_dev_info->dmu_guid)
|
||||
pmc_core_punit_pmt_init(pmcdev, pmc_dev_info->dmu_guid);
|
||||
|
||||
if (ssram)
|
||||
return pmc_core_ssram_get_lpm_reqs(pmcdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct x86_cpu_id intel_pmc_core_ids[] = {
|
||||
X86_MATCH_VFM(INTEL_SKYLAKE_L, spt_core_init),
|
||||
X86_MATCH_VFM(INTEL_SKYLAKE, spt_core_init),
|
||||
X86_MATCH_VFM(INTEL_KABYLAKE_L, spt_core_init),
|
||||
X86_MATCH_VFM(INTEL_KABYLAKE, spt_core_init),
|
||||
X86_MATCH_VFM(INTEL_CANNONLAKE_L, cnp_core_init),
|
||||
X86_MATCH_VFM(INTEL_ICELAKE_L, icl_core_init),
|
||||
X86_MATCH_VFM(INTEL_ICELAKE_NNPI, icl_core_init),
|
||||
X86_MATCH_VFM(INTEL_COMETLAKE, cnp_core_init),
|
||||
X86_MATCH_VFM(INTEL_COMETLAKE_L, cnp_core_init),
|
||||
X86_MATCH_VFM(INTEL_TIGERLAKE_L, tgl_l_core_init),
|
||||
X86_MATCH_VFM(INTEL_TIGERLAKE, tgl_core_init),
|
||||
X86_MATCH_VFM(INTEL_ATOM_TREMONT, tgl_l_core_init),
|
||||
X86_MATCH_VFM(INTEL_ATOM_TREMONT_L, icl_core_init),
|
||||
X86_MATCH_VFM(INTEL_ROCKETLAKE, tgl_core_init),
|
||||
X86_MATCH_VFM(INTEL_ALDERLAKE_L, tgl_l_core_init),
|
||||
X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, tgl_l_core_init),
|
||||
X86_MATCH_VFM(INTEL_ALDERLAKE, adl_core_init),
|
||||
X86_MATCH_VFM(INTEL_RAPTORLAKE_P, tgl_l_core_init),
|
||||
X86_MATCH_VFM(INTEL_RAPTORLAKE, adl_core_init),
|
||||
X86_MATCH_VFM(INTEL_RAPTORLAKE_S, adl_core_init),
|
||||
X86_MATCH_VFM(INTEL_METEORLAKE_L, mtl_core_init),
|
||||
X86_MATCH_VFM(INTEL_ARROWLAKE, arl_core_init),
|
||||
X86_MATCH_VFM(INTEL_LUNARLAKE_M, lnl_core_init),
|
||||
X86_MATCH_VFM(INTEL_SKYLAKE_L, &spt_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_SKYLAKE, &spt_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_KABYLAKE_L, &spt_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_KABYLAKE, &spt_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_CANNONLAKE_L, &cnp_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ICELAKE_L, &icl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ICELAKE_NNPI, &icl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_COMETLAKE, &cnp_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_COMETLAKE_L, &cnp_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_TIGERLAKE_L, &tgl_l_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_TIGERLAKE, &tgl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ATOM_TREMONT, &tgl_l_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ATOM_TREMONT_L, &icl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ROCKETLAKE, &tgl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ALDERLAKE_L, &tgl_l_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, &tgl_l_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ALDERLAKE, &adl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_RAPTORLAKE_P, &tgl_l_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_RAPTORLAKE, &adl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_RAPTORLAKE_S, &adl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_METEORLAKE_L, &mtl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ARROWLAKE, &arl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ARROWLAKE_H, &arl_h_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_ARROWLAKE_U, &arl_h_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_LUNARLAKE_M, &lnl_pmc_dev),
|
||||
X86_MATCH_VFM(INTEL_PANTHERLAKE_L, &ptl_pmc_dev),
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_ids);
|
||||
|
||||
static const struct pci_device_id pmc_pci_ids[] = {
|
||||
{ PCI_VDEVICE(INTEL, SPT_PMC_PCI_DEVICE_ID) },
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* This quirk can be used on those platforms where
|
||||
* the platform BIOS enforces 24Mhz crystal to shutdown
|
||||
|
|
@ -1452,7 +1492,7 @@ static int pmc_core_probe(struct platform_device *pdev)
|
|||
static bool device_initialized;
|
||||
struct pmc_dev *pmcdev;
|
||||
const struct x86_cpu_id *cpu_id;
|
||||
int (*core_init)(struct pmc_dev *pmcdev);
|
||||
struct pmc_dev_info *pmc_dev_info;
|
||||
struct pmc *primary_pmc;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1472,7 +1512,7 @@ static int pmc_core_probe(struct platform_device *pdev)
|
|||
if (!cpu_id)
|
||||
return -ENODEV;
|
||||
|
||||
core_init = (int (*)(struct pmc_dev *))cpu_id->driver_data;
|
||||
pmc_dev_info = (struct pmc_dev_info *)cpu_id->driver_data;
|
||||
|
||||
/* Primary PMC */
|
||||
primary_pmc = devm_kzalloc(&pdev->dev, sizeof(*primary_pmc), GFP_KERNEL);
|
||||
|
|
@ -1489,16 +1529,13 @@ static int pmc_core_probe(struct platform_device *pdev)
|
|||
if (!pmcdev->pkgc_res_cnt)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here
|
||||
* Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap
|
||||
* in this case.
|
||||
*/
|
||||
if (core_init == spt_core_init && !pci_dev_present(pmc_pci_ids))
|
||||
core_init = cnp_core_init;
|
||||
|
||||
mutex_init(&pmcdev->lock);
|
||||
ret = core_init(pmcdev);
|
||||
|
||||
if (pmc_dev_info->init)
|
||||
ret = pmc_dev_info->init(pmcdev, pmc_dev_info);
|
||||
else
|
||||
ret = generic_core_init(pmcdev, pmc_dev_info);
|
||||
|
||||
if (ret) {
|
||||
pmc_core_clean_structure(pdev);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -285,6 +285,14 @@ enum ppfear_regs {
|
|||
#define LNL_PPFEAR_NUM_ENTRIES 12
|
||||
#define LNL_S0IX_BLOCKER_OFFSET 0x2004
|
||||
|
||||
/* Panther Lake Power Management Controller register offsets */
|
||||
#define PTL_LPM_NUM_MAPS 14
|
||||
#define PTL_PMC_LTR_SATA2 0x1B90
|
||||
#define PTL_PMC_LTR_PMC 0x1BA8
|
||||
#define PTL_PMC_LTR_CUR_ASLT 0x1C28
|
||||
#define PTL_PMC_LTR_CUR_PLT 0x1C2C
|
||||
#define PTL_PCD_PMC_MMIO_REG_LEN 0x31A8
|
||||
|
||||
extern const char *pmc_lpm_modes[];
|
||||
|
||||
struct pmc_bit_map {
|
||||
|
|
@ -430,178 +438,77 @@ struct pmc_dev {
|
|||
|
||||
enum pmc_index {
|
||||
PMC_IDX_MAIN,
|
||||
PMC_IDX_SOC = PMC_IDX_MAIN,
|
||||
PMC_IDX_IOE,
|
||||
PMC_IDX_PCH,
|
||||
PMC_IDX_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pmc_dev_info - Structure to keep PMC device info
|
||||
* @pci_func: Function number of the primary PMC
|
||||
* @dmu_guid: Die Management Unit GUID
|
||||
* @regmap_list: Pointer to a list of pmc_info structure that could be
|
||||
* available for the platform. When set, this field implies
|
||||
* SSRAM support.
|
||||
* @map: Pointer to a pmc_reg_map struct that contains platform
|
||||
* specific attributes of the primary PMC
|
||||
* @suspend: Function to perform platform specific suspend
|
||||
* @resume: Function to perform platform specific resume
|
||||
* @init: Function to perform platform specific init action
|
||||
*/
|
||||
struct pmc_dev_info {
|
||||
u8 pci_func;
|
||||
u32 dmu_guid;
|
||||
struct pmc_info *regmap_list;
|
||||
const struct pmc_reg_map *map;
|
||||
void (*suspend)(struct pmc_dev *pmcdev);
|
||||
int (*resume)(struct pmc_dev *pmcdev);
|
||||
int (*init)(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info);
|
||||
};
|
||||
|
||||
extern const struct pmc_bit_map msr_map[];
|
||||
extern const struct pmc_bit_map spt_pll_map[];
|
||||
extern const struct pmc_bit_map spt_mphy_map[];
|
||||
extern const struct pmc_bit_map spt_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_spt_pfear_map[];
|
||||
extern const struct pmc_bit_map spt_ltr_show_map[];
|
||||
extern const struct pmc_reg_map spt_reg_map;
|
||||
extern const struct pmc_bit_map cnp_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_cnp_pfear_map[];
|
||||
extern const struct pmc_bit_map cnp_slps0_dbg0_map[];
|
||||
extern const struct pmc_bit_map cnp_slps0_dbg1_map[];
|
||||
extern const struct pmc_bit_map cnp_slps0_dbg2_map[];
|
||||
extern const struct pmc_bit_map *cnp_slps0_dbg_maps[];
|
||||
extern const struct pmc_bit_map cnp_ltr_show_map[];
|
||||
extern const struct pmc_reg_map cnp_reg_map;
|
||||
extern const struct pmc_bit_map icl_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_icl_pfear_map[];
|
||||
extern const struct pmc_reg_map icl_reg_map;
|
||||
extern const struct pmc_bit_map tgl_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_tgl_pfear_map[];
|
||||
extern const struct pmc_bit_map tgl_clocksource_status_map[];
|
||||
extern const struct pmc_bit_map tgl_power_gating_status_map[];
|
||||
extern const struct pmc_bit_map tgl_d3_status_map[];
|
||||
extern const struct pmc_bit_map tgl_vnn_req_status_map[];
|
||||
extern const struct pmc_bit_map tgl_vnn_misc_status_map[];
|
||||
extern const struct pmc_bit_map tgl_signal_status_map[];
|
||||
extern const struct pmc_bit_map *tgl_lpm_maps[];
|
||||
extern const struct pmc_reg_map tgl_reg_map;
|
||||
extern const struct pmc_reg_map tgl_h_reg_map;
|
||||
extern const struct pmc_bit_map adl_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_adl_pfear_map[];
|
||||
extern const struct pmc_bit_map adl_ltr_show_map[];
|
||||
extern const struct pmc_bit_map adl_clocksource_status_map[];
|
||||
extern const struct pmc_bit_map adl_power_gating_status_0_map[];
|
||||
extern const struct pmc_bit_map adl_power_gating_status_1_map[];
|
||||
extern const struct pmc_bit_map adl_power_gating_status_2_map[];
|
||||
extern const struct pmc_bit_map adl_d3_status_0_map[];
|
||||
extern const struct pmc_bit_map adl_d3_status_1_map[];
|
||||
extern const struct pmc_bit_map adl_d3_status_2_map[];
|
||||
extern const struct pmc_bit_map adl_d3_status_3_map[];
|
||||
extern const struct pmc_bit_map adl_vnn_req_status_0_map[];
|
||||
extern const struct pmc_bit_map adl_vnn_req_status_1_map[];
|
||||
extern const struct pmc_bit_map adl_vnn_req_status_2_map[];
|
||||
extern const struct pmc_bit_map adl_vnn_req_status_3_map[];
|
||||
extern const struct pmc_bit_map adl_vnn_misc_status_map[];
|
||||
extern const struct pmc_bit_map *adl_lpm_maps[];
|
||||
extern const struct pmc_reg_map adl_reg_map;
|
||||
extern const struct pmc_bit_map mtl_socm_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_mtl_socm_pfear_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_ltr_show_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_clocksource_status_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_power_gating_status_0_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_power_gating_status_1_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_power_gating_status_2_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_d3_status_0_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_d3_status_1_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_d3_status_2_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_d3_status_3_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_vnn_misc_status_map[];
|
||||
extern const struct pmc_bit_map mtl_socm_signal_status_map[];
|
||||
extern const struct pmc_bit_map *mtl_socm_lpm_maps[];
|
||||
extern const struct pmc_reg_map mtl_socm_reg_map;
|
||||
extern const struct pmc_bit_map mtl_ioep_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_mtl_ioep_pfear_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_ltr_show_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_clocksource_status_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_d3_status_0_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_d3_status_1_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_d3_status_2_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_d3_status_3_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[];
|
||||
extern const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[];
|
||||
extern const struct pmc_bit_map *mtl_ioep_lpm_maps[];
|
||||
extern const struct pmc_reg_map mtl_ioep_reg_map;
|
||||
extern const struct pmc_bit_map mtl_ioem_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_mtl_ioem_pfear_map[];
|
||||
extern const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[];
|
||||
extern const struct pmc_bit_map mtl_ioem_vnn_req_status_1_map[];
|
||||
extern const struct pmc_bit_map *mtl_ioem_lpm_maps[];
|
||||
extern const struct pmc_reg_map mtl_ioem_reg_map;
|
||||
extern const struct pmc_reg_map lnl_socm_reg_map;
|
||||
|
||||
/* LNL */
|
||||
extern const struct pmc_bit_map lnl_ltr_show_map[];
|
||||
extern const struct pmc_bit_map lnl_clocksource_status_map[];
|
||||
extern const struct pmc_bit_map lnl_power_gating_status_0_map[];
|
||||
extern const struct pmc_bit_map lnl_power_gating_status_1_map[];
|
||||
extern const struct pmc_bit_map lnl_power_gating_status_2_map[];
|
||||
extern const struct pmc_bit_map lnl_d3_status_0_map[];
|
||||
extern const struct pmc_bit_map lnl_d3_status_1_map[];
|
||||
extern const struct pmc_bit_map lnl_d3_status_2_map[];
|
||||
extern const struct pmc_bit_map lnl_d3_status_3_map[];
|
||||
extern const struct pmc_bit_map lnl_vnn_req_status_0_map[];
|
||||
extern const struct pmc_bit_map lnl_vnn_req_status_1_map[];
|
||||
extern const struct pmc_bit_map lnl_vnn_req_status_2_map[];
|
||||
extern const struct pmc_bit_map lnl_vnn_req_status_3_map[];
|
||||
extern const struct pmc_bit_map lnl_vnn_misc_status_map[];
|
||||
extern const struct pmc_bit_map *lnl_lpm_maps[];
|
||||
extern const struct pmc_bit_map *lnl_blk_maps[];
|
||||
extern const struct pmc_bit_map lnl_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_lnl_pfear_map[];
|
||||
extern const struct pmc_bit_map lnl_signal_status_map[];
|
||||
|
||||
/* ARL */
|
||||
extern const struct pmc_bit_map arl_socs_ltr_show_map[];
|
||||
extern const struct pmc_bit_map arl_socs_clocksource_status_map[];
|
||||
extern const struct pmc_bit_map arl_socs_power_gating_status_0_map[];
|
||||
extern const struct pmc_bit_map arl_socs_power_gating_status_1_map[];
|
||||
extern const struct pmc_bit_map arl_socs_power_gating_status_2_map[];
|
||||
extern const struct pmc_bit_map arl_socs_d3_status_2_map[];
|
||||
extern const struct pmc_bit_map arl_socs_d3_status_3_map[];
|
||||
extern const struct pmc_bit_map arl_socs_vnn_req_status_3_map[];
|
||||
extern const struct pmc_bit_map *arl_socs_lpm_maps[];
|
||||
extern const struct pmc_bit_map arl_socs_pfear_map[];
|
||||
extern const struct pmc_bit_map *ext_arl_socs_pfear_map[];
|
||||
extern const struct pmc_reg_map arl_socs_reg_map;
|
||||
extern const struct pmc_bit_map arl_pchs_ltr_show_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_clocksource_status_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_power_gating_status_0_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_power_gating_status_1_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_power_gating_status_2_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_d3_status_0_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_d3_status_1_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_d3_status_2_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_d3_status_3_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_vnn_req_status_0_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_vnn_misc_status_map[];
|
||||
extern const struct pmc_bit_map arl_pchs_signal_status_map[];
|
||||
extern const struct pmc_bit_map *arl_pchs_lpm_maps[];
|
||||
extern const struct pmc_reg_map arl_pchs_reg_map;
|
||||
|
||||
extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
|
||||
extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev);
|
||||
void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev);
|
||||
int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev);
|
||||
int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore);
|
||||
|
||||
int pmc_core_resume_common(struct pmc_dev *pmcdev);
|
||||
int get_primary_reg_base(struct pmc *pmc);
|
||||
extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
|
||||
extern void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid);
|
||||
extern void pmc_core_set_device_d3(unsigned int device);
|
||||
void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
|
||||
void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid);
|
||||
void pmc_core_set_device_d3(unsigned int device);
|
||||
|
||||
extern int pmc_core_ssram_init(struct pmc_dev *pmcdev, int func);
|
||||
int pmc_core_ssram_init(struct pmc_dev *pmcdev, int func);
|
||||
|
||||
int spt_core_init(struct pmc_dev *pmcdev);
|
||||
int cnp_core_init(struct pmc_dev *pmcdev);
|
||||
int icl_core_init(struct pmc_dev *pmcdev);
|
||||
int tgl_core_init(struct pmc_dev *pmcdev);
|
||||
int tgl_l_core_init(struct pmc_dev *pmcdev);
|
||||
int tgl_core_generic_init(struct pmc_dev *pmcdev, int pch_tp);
|
||||
int adl_core_init(struct pmc_dev *pmcdev);
|
||||
int mtl_core_init(struct pmc_dev *pmcdev);
|
||||
int arl_core_init(struct pmc_dev *pmcdev);
|
||||
int lnl_core_init(struct pmc_dev *pmcdev);
|
||||
int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info);
|
||||
|
||||
extern struct pmc_dev_info spt_pmc_dev;
|
||||
extern struct pmc_dev_info cnp_pmc_dev;
|
||||
extern struct pmc_dev_info icl_pmc_dev;
|
||||
extern struct pmc_dev_info tgl_l_pmc_dev;
|
||||
extern struct pmc_dev_info tgl_pmc_dev;
|
||||
extern struct pmc_dev_info adl_pmc_dev;
|
||||
extern struct pmc_dev_info mtl_pmc_dev;
|
||||
extern struct pmc_dev_info arl_pmc_dev;
|
||||
extern struct pmc_dev_info arl_h_pmc_dev;
|
||||
extern struct pmc_dev_info lnl_pmc_dev;
|
||||
extern struct pmc_dev_info ptl_pmc_dev;
|
||||
|
||||
void cnl_suspend(struct pmc_dev *pmcdev);
|
||||
int cnl_resume(struct pmc_dev *pmcdev);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "core.h"
|
||||
|
||||
const struct pmc_bit_map icl_pfear_map[] = {
|
||||
static const struct pmc_bit_map icl_pfear_map[] = {
|
||||
{"RES_65", BIT(0)},
|
||||
{"RES_66", BIT(1)},
|
||||
{"RES_67", BIT(2)},
|
||||
|
|
@ -22,7 +22,7 @@ const struct pmc_bit_map icl_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_icl_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_icl_pfear_map[] = {
|
||||
/*
|
||||
* Check intel_pmc_core_ids[] users of icl_reg_map for
|
||||
* a list of core SoCs using this.
|
||||
|
|
@ -32,7 +32,7 @@ const struct pmc_bit_map *ext_icl_pfear_map[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_reg_map icl_reg_map = {
|
||||
static const struct pmc_reg_map icl_reg_map = {
|
||||
.pfear_sts = ext_icl_pfear_map,
|
||||
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
|
||||
.slp_s0_res_counter_step = ICL_PMC_SLP_S0_RES_COUNTER_STEP,
|
||||
|
|
@ -50,18 +50,6 @@ const struct pmc_reg_map icl_reg_map = {
|
|||
.etr3_offset = ETR3_OFFSET,
|
||||
};
|
||||
|
||||
int icl_core_init(struct pmc_dev *pmcdev)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
|
||||
int ret;
|
||||
|
||||
pmc->map = &icl_reg_map;
|
||||
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
struct pmc_dev_info icl_pmc_dev = {
|
||||
.map = &icl_reg_map,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "core.h"
|
||||
|
||||
const struct pmc_bit_map lnl_ltr_show_map[] = {
|
||||
static const struct pmc_bit_map lnl_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
|
||||
{"SATA", CNP_PMC_LTR_SATA},
|
||||
|
|
@ -55,7 +55,7 @@ const struct pmc_bit_map lnl_ltr_show_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_power_gating_status_0_map[] = {
|
||||
static const struct pmc_bit_map lnl_power_gating_status_0_map[] = {
|
||||
{"PMC_PGD0_PG_STS", BIT(0), 0},
|
||||
{"FUSE_OSSE_PGD0_PG_STS", BIT(1), 0},
|
||||
{"ESPISPI_PGD0_PG_STS", BIT(2), 0},
|
||||
|
|
@ -91,7 +91,7 @@ const struct pmc_bit_map lnl_power_gating_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_power_gating_status_1_map[] = {
|
||||
static const struct pmc_bit_map lnl_power_gating_status_1_map[] = {
|
||||
{"USBR0_PGD0_PG_STS", BIT(0), 1},
|
||||
{"SUSRAM_PGD0_PG_STS", BIT(1), 1},
|
||||
{"SMT1_PGD0_PG_STS", BIT(2), 1},
|
||||
|
|
@ -127,7 +127,7 @@ const struct pmc_bit_map lnl_power_gating_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_power_gating_status_2_map[] = {
|
||||
static const struct pmc_bit_map lnl_power_gating_status_2_map[] = {
|
||||
{"PSF8_PGD0_PG_STS", BIT(0), 0},
|
||||
{"SBR16B2_PGD0_PG_STS", BIT(1), 0},
|
||||
{"D2D_IPU_PGD0_PG_STS", BIT(2), 1},
|
||||
|
|
@ -163,7 +163,7 @@ const struct pmc_bit_map lnl_power_gating_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_d3_status_0_map[] = {
|
||||
static const struct pmc_bit_map lnl_d3_status_0_map[] = {
|
||||
{"LPSS_D3_STS", BIT(3), 1},
|
||||
{"XDCI_D3_STS", BIT(4), 1},
|
||||
{"XHCI_D3_STS", BIT(5), 1},
|
||||
|
|
@ -175,7 +175,7 @@ const struct pmc_bit_map lnl_d3_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_d3_status_1_map[] = {
|
||||
static const struct pmc_bit_map lnl_d3_status_1_map[] = {
|
||||
{"OSSE_SMT1_D3_STS", BIT(7), 0},
|
||||
{"GBE_D3_STS", BIT(19), 0},
|
||||
{"ITSS_D3_STS", BIT(23), 0},
|
||||
|
|
@ -185,7 +185,7 @@ const struct pmc_bit_map lnl_d3_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_d3_status_2_map[] = {
|
||||
static const struct pmc_bit_map lnl_d3_status_2_map[] = {
|
||||
{"ESE_D3_STS", BIT(0), 0},
|
||||
{"CSMERTC_D3_STS", BIT(1), 0},
|
||||
{"SUSRAM_D3_STS", BIT(2), 0},
|
||||
|
|
@ -205,7 +205,7 @@ const struct pmc_bit_map lnl_d3_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_d3_status_3_map[] = {
|
||||
static const struct pmc_bit_map lnl_d3_status_3_map[] = {
|
||||
{"THC0_D3_STS", BIT(14), 1},
|
||||
{"THC1_D3_STS", BIT(15), 1},
|
||||
{"OSSE_SMT3_D3_STS", BIT(21), 0},
|
||||
|
|
@ -213,14 +213,14 @@ const struct pmc_bit_map lnl_d3_status_3_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_vnn_req_status_0_map[] = {
|
||||
static const struct pmc_bit_map lnl_vnn_req_status_0_map[] = {
|
||||
{"LPSS_VNN_REQ_STS", BIT(3), 1},
|
||||
{"OSSE_VNN_REQ_STS", BIT(15), 1},
|
||||
{"ESPISPI_VNN_REQ_STS", BIT(18), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_vnn_req_status_1_map[] = {
|
||||
static const struct pmc_bit_map lnl_vnn_req_status_1_map[] = {
|
||||
{"NPK_VNN_REQ_STS", BIT(4), 1},
|
||||
{"OSSE_SMT1_VNN_REQ_STS", BIT(7), 1},
|
||||
{"DFXAGG_VNN_REQ_STS", BIT(8), 0},
|
||||
|
|
@ -232,7 +232,7 @@ const struct pmc_bit_map lnl_vnn_req_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_vnn_req_status_2_map[] = {
|
||||
static const struct pmc_bit_map lnl_vnn_req_status_2_map[] = {
|
||||
{"eSE_VNN_REQ_STS", BIT(0), 1},
|
||||
{"CSMERTC_VNN_REQ_STS", BIT(1), 1},
|
||||
{"CSE_VNN_REQ_STS", BIT(4), 1},
|
||||
|
|
@ -249,14 +249,14 @@ const struct pmc_bit_map lnl_vnn_req_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_vnn_req_status_3_map[] = {
|
||||
static const struct pmc_bit_map lnl_vnn_req_status_3_map[] = {
|
||||
{"DISP_SHIM_VNN_REQ_STS", BIT(2), 0},
|
||||
{"DTS0_VNN_REQ_STS", BIT(7), 0},
|
||||
{"GPIOCOM5_VNN_REQ_STS", BIT(11), 2},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_vnn_misc_status_map[] = {
|
||||
static const struct pmc_bit_map lnl_vnn_misc_status_map[] = {
|
||||
{"CPU_C10_REQ_STS", BIT(0), 0},
|
||||
{"TS_OFF_REQ_STS", BIT(1), 0},
|
||||
{"PNDE_MET_REQ_STS", BIT(2), 1},
|
||||
|
|
@ -292,7 +292,7 @@ const struct pmc_bit_map lnl_vnn_misc_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_clocksource_status_map[] = {
|
||||
static const struct pmc_bit_map lnl_clocksource_status_map[] = {
|
||||
{"AON2_OFF_STS", BIT(0), 0},
|
||||
{"AON3_OFF_STS", BIT(1), 1},
|
||||
{"AON4_OFF_STS", BIT(2), 1},
|
||||
|
|
@ -317,7 +317,7 @@ const struct pmc_bit_map lnl_clocksource_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_signal_status_map[] = {
|
||||
static const struct pmc_bit_map lnl_signal_status_map[] = {
|
||||
{"LSX_Wake0_STS", BIT(0), 0},
|
||||
{"LSX_Wake1_STS", BIT(1), 0},
|
||||
{"LSX_Wake2_STS", BIT(2), 0},
|
||||
|
|
@ -337,7 +337,7 @@ const struct pmc_bit_map lnl_signal_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_rsc_status_map[] = {
|
||||
static const struct pmc_bit_map lnl_rsc_status_map[] = {
|
||||
{"Memory", 0, 1},
|
||||
{"PSF0", 0, 1},
|
||||
{"PSF4", 0, 1},
|
||||
|
|
@ -349,7 +349,7 @@ const struct pmc_bit_map lnl_rsc_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *lnl_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *lnl_lpm_maps[] = {
|
||||
lnl_clocksource_status_map,
|
||||
lnl_power_gating_status_0_map,
|
||||
lnl_power_gating_status_1_map,
|
||||
|
|
@ -367,7 +367,7 @@ const struct pmc_bit_map *lnl_lpm_maps[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *lnl_blk_maps[] = {
|
||||
static const struct pmc_bit_map *lnl_blk_maps[] = {
|
||||
lnl_power_gating_status_0_map,
|
||||
lnl_power_gating_status_1_map,
|
||||
lnl_power_gating_status_2_map,
|
||||
|
|
@ -386,7 +386,7 @@ const struct pmc_bit_map *lnl_blk_maps[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map lnl_pfear_map[] = {
|
||||
static const struct pmc_bit_map lnl_pfear_map[] = {
|
||||
{"PMC_0", BIT(0)},
|
||||
{"FUSE_OSSE", BIT(1)},
|
||||
{"ESPISPI", BIT(2)},
|
||||
|
|
@ -498,12 +498,12 @@ const struct pmc_bit_map lnl_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_lnl_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_lnl_pfear_map[] = {
|
||||
lnl_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_reg_map lnl_socm_reg_map = {
|
||||
static const struct pmc_reg_map lnl_socm_reg_map = {
|
||||
.pfear_sts = ext_lnl_pfear_map,
|
||||
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
|
||||
.slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
|
||||
|
|
@ -550,22 +550,15 @@ static int lnl_resume(struct pmc_dev *pmcdev)
|
|||
return cnl_resume(pmcdev);
|
||||
}
|
||||
|
||||
int lnl_core_init(struct pmc_dev *pmcdev)
|
||||
static int lnl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
int ret;
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
|
||||
|
||||
lnl_d3_fixup();
|
||||
|
||||
pmcdev->suspend = cnl_suspend;
|
||||
pmcdev->resume = lnl_resume;
|
||||
|
||||
pmc->map = &lnl_socm_reg_map;
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
|
||||
return 0;
|
||||
return generic_core_init(pmcdev, pmc_dev_info);
|
||||
}
|
||||
|
||||
struct pmc_dev_info lnl_pmc_dev = {
|
||||
.map = &lnl_socm_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = lnl_resume,
|
||||
.init = lnl_core_init,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -102,12 +102,12 @@ const struct pmc_bit_map mtl_socm_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = {
|
||||
mtl_socm_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_ltr_show_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
|
||||
{"SATA", CNP_PMC_LTR_SATA},
|
||||
|
|
@ -141,7 +141,7 @@ const struct pmc_bit_map mtl_socm_ltr_show_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_clocksource_status_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_clocksource_status_map[] = {
|
||||
{"AON2_OFF_STS", BIT(0)},
|
||||
{"AON3_OFF_STS", BIT(1)},
|
||||
{"AON4_OFF_STS", BIT(2)},
|
||||
|
|
@ -167,7 +167,7 @@ const struct pmc_bit_map mtl_socm_clocksource_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = {
|
||||
{"PMC_PGD0_PG_STS", BIT(0)},
|
||||
{"DMI_PGD0_PG_STS", BIT(1)},
|
||||
{"ESPISPI_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -203,7 +203,7 @@ const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = {
|
||||
{"USBR0_PGD0_PG_STS", BIT(0)},
|
||||
{"SUSRAM_PGD0_PG_STS", BIT(1)},
|
||||
{"SMT1_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -239,7 +239,7 @@ const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = {
|
||||
{"PSF8_PGD0_PG_STS", BIT(0)},
|
||||
{"FIA_PGD0_PG_STS", BIT(1)},
|
||||
{"SOC_D2D_PGD1_PG_STS", BIT(2)},
|
||||
|
|
@ -291,7 +291,7 @@ const struct pmc_bit_map mtl_socm_d3_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_d3_status_2_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_d3_status_2_map[] = {
|
||||
{"GNA_D3_STS", BIT(0)},
|
||||
{"CSMERTC_D3_STS", BIT(1)},
|
||||
{"SUSRAM_D3_STS", BIT(2)},
|
||||
|
|
@ -310,7 +310,7 @@ const struct pmc_bit_map mtl_socm_d3_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_d3_status_3_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_d3_status_3_map[] = {
|
||||
{"ESE_D3_STS", BIT(2)},
|
||||
{"GBETSN_D3_STS", BIT(13)},
|
||||
{"THC0_D3_STS", BIT(14)},
|
||||
|
|
@ -353,7 +353,7 @@ const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = {
|
||||
static const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = {
|
||||
{"ESE_VNN_REQ_STS", BIT(2)},
|
||||
{"DTS0_VNN_REQ_STS", BIT(7)},
|
||||
{"GPIOCOM5_VNN_REQ_STS", BIT(11)},
|
||||
|
|
@ -432,7 +432,7 @@ const struct pmc_bit_map mtl_socm_signal_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *mtl_socm_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *mtl_socm_lpm_maps[] = {
|
||||
mtl_socm_clocksource_status_map,
|
||||
mtl_socm_power_gating_status_0_map,
|
||||
mtl_socm_power_gating_status_1_map,
|
||||
|
|
@ -476,7 +476,7 @@ const struct pmc_reg_map mtl_socm_reg_map = {
|
|||
.lpm_reg_index = MTL_LPM_REG_INDEX,
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_pfear_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_pfear_map[] = {
|
||||
{"PMC_0", BIT(0)},
|
||||
{"OPI", BIT(1)},
|
||||
{"TCSS", BIT(2)},
|
||||
|
|
@ -563,12 +563,12 @@ const struct pmc_bit_map mtl_ioep_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = {
|
||||
mtl_ioep_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_ltr_show_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
|
||||
{"SATA", CNP_PMC_LTR_SATA},
|
||||
|
|
@ -600,7 +600,7 @@ const struct pmc_bit_map mtl_ioep_ltr_show_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = {
|
||||
{"AON2_OFF_STS", BIT(0)},
|
||||
{"AON3_OFF_STS", BIT(1)},
|
||||
{"AON4_OFF_STS", BIT(2)},
|
||||
|
|
@ -623,7 +623,7 @@ const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = {
|
||||
{"PMC_PGD0_PG_STS", BIT(0)},
|
||||
{"DMI_PGD0_PG_STS", BIT(1)},
|
||||
{"TCSS_PGD0_PG_STS", BIT(2)},
|
||||
|
|
@ -650,7 +650,7 @@ const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = {
|
||||
{"PSF9_PGD0_PG_STS", BIT(0)},
|
||||
{"MPFPW4_PGD0_PG_STS", BIT(1)},
|
||||
{"SBR0_PGD0_PG_STS", BIT(8)},
|
||||
|
|
@ -668,7 +668,7 @@ const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = {
|
||||
{"FIA_PGD0_PG_STS", BIT(1)},
|
||||
{"FIA_P_PGD0_PG_STS", BIT(3)},
|
||||
{"TAM_PGD0_PG_STS", BIT(4)},
|
||||
|
|
@ -680,7 +680,7 @@ const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = {
|
||||
{"SPF_D3_STS", BIT(0)},
|
||||
{"SPA_D3_STS", BIT(12)},
|
||||
{"SPB_D3_STS", BIT(13)},
|
||||
|
|
@ -691,43 +691,43 @@ const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = {
|
||||
{"GBETSN1_D3_STS", BIT(14)},
|
||||
{"P2S_D3_STS", BIT(24)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = {
|
||||
{"GBETSN_D3_STS", BIT(13)},
|
||||
{"ACE_D3_STS", BIT(23)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = {
|
||||
{"FIA_VNN_REQ_STS", BIT(17)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = {
|
||||
{"DFXAGG_VNN_REQ_STS", BIT(8)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = {
|
||||
{"DTS0_VNN_REQ_STS", BIT(7)},
|
||||
{"DISP_VNN_REQ_STS", BIT(19)},
|
||||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = {
|
||||
{"CPU_C10_REQ_STS", BIT(0)},
|
||||
{"TS_OFF_REQ_STS", BIT(1)},
|
||||
{"PNDE_MET_REQ_STS", BIT(2)},
|
||||
|
|
@ -762,7 +762,7 @@ const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *mtl_ioep_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *mtl_ioep_lpm_maps[] = {
|
||||
mtl_ioep_clocksource_status_map,
|
||||
mtl_ioep_power_gating_status_0_map,
|
||||
mtl_ioep_power_gating_status_1_map,
|
||||
|
|
@ -800,7 +800,7 @@ const struct pmc_reg_map mtl_ioep_reg_map = {
|
|||
.lpm_reg_index = MTL_LPM_REG_INDEX,
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioem_pfear_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioem_pfear_map[] = {
|
||||
{"PMC_0", BIT(0)},
|
||||
{"OPI", BIT(1)},
|
||||
{"TCSS", BIT(2)},
|
||||
|
|
@ -887,12 +887,12 @@ const struct pmc_bit_map mtl_ioem_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = {
|
||||
mtl_ioem_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = {
|
||||
static const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = {
|
||||
{"PSF9_PGD0_PG_STS", BIT(0)},
|
||||
{"MPFPW4_PGD0_PG_STS", BIT(1)},
|
||||
{"SBR0_PGD0_PG_STS", BIT(8)},
|
||||
|
|
@ -909,7 +909,7 @@ const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *mtl_ioem_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *mtl_ioem_lpm_maps[] = {
|
||||
mtl_ioep_clocksource_status_map,
|
||||
mtl_ioep_power_gating_status_0_map,
|
||||
mtl_ioem_power_gating_status_1_map,
|
||||
|
|
@ -927,7 +927,7 @@ const struct pmc_bit_map *mtl_ioem_lpm_maps[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_reg_map mtl_ioem_reg_map = {
|
||||
static const struct pmc_reg_map mtl_ioem_reg_map = {
|
||||
.regmap_length = MTL_IOE_PMC_MMIO_REG_LEN,
|
||||
.pfear_sts = ext_mtl_ioem_pfear_map,
|
||||
.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
|
||||
|
|
@ -990,39 +990,18 @@ static int mtl_resume(struct pmc_dev *pmcdev)
|
|||
return cnl_resume(pmcdev);
|
||||
}
|
||||
|
||||
int mtl_core_init(struct pmc_dev *pmcdev)
|
||||
static int mtl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
|
||||
int ret;
|
||||
int func = 2;
|
||||
bool ssram_init = true;
|
||||
|
||||
mtl_d3_fixup();
|
||||
|
||||
pmcdev->suspend = cnl_suspend;
|
||||
pmcdev->resume = mtl_resume;
|
||||
pmcdev->regmap_list = mtl_pmc_info_list;
|
||||
|
||||
/*
|
||||
* If ssram init fails use legacy method to at least get the
|
||||
* primary PMC
|
||||
*/
|
||||
ret = pmc_core_ssram_init(pmcdev, func);
|
||||
if (ret) {
|
||||
ssram_init = false;
|
||||
dev_warn(&pmcdev->pdev->dev,
|
||||
"ssram init failed, %d, using legacy init\n", ret);
|
||||
pmc->map = &mtl_socm_reg_map;
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
pmc_core_punit_pmt_init(pmcdev, MTL_PMT_DMU_GUID);
|
||||
|
||||
if (ssram_init)
|
||||
return pmc_core_ssram_get_lpm_reqs(pmcdev);
|
||||
|
||||
return 0;
|
||||
return generic_core_init(pmcdev, pmc_dev_info);
|
||||
}
|
||||
|
||||
struct pmc_dev_info mtl_pmc_dev = {
|
||||
.pci_func = 2,
|
||||
.dmu_guid = MTL_PMT_DMU_GUID,
|
||||
.regmap_list = mtl_pmc_info_list,
|
||||
.map = &mtl_socm_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = mtl_resume,
|
||||
.init = mtl_core_init,
|
||||
};
|
||||
|
|
|
|||
550
drivers/platform/x86/intel/pmc/ptl.c
Normal file
550
drivers/platform/x86/intel/pmc/ptl.c
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* This file contains platform specific structure definitions
|
||||
* and init function used by Panther Lake PCH.
|
||||
*
|
||||
* Copyright (c) 2025, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_pfear_map[] = {
|
||||
{"PMC_0", BIT(0)},
|
||||
{"FUSE_OSSE", BIT(1)},
|
||||
{"ESPISPI", BIT(2)},
|
||||
{"XHCI", BIT(3)},
|
||||
{"SPA", BIT(4)},
|
||||
{"SPB", BIT(5)},
|
||||
{"MPFPW2", BIT(6)},
|
||||
{"GBE", BIT(7)},
|
||||
|
||||
{"SBR16B20", BIT(0)},
|
||||
{"SBR8B20", BIT(1)},
|
||||
{"SBR16B21", BIT(2)},
|
||||
{"DBG_SBR16B", BIT(3)},
|
||||
{"OSSE_HOTHAM", BIT(4)},
|
||||
{"D2D_DISP_1", BIT(5)},
|
||||
{"LPSS", BIT(6)},
|
||||
{"LPC", BIT(7)},
|
||||
|
||||
{"SMB", BIT(0)},
|
||||
{"ISH", BIT(1)},
|
||||
{"SBR16B2", BIT(2)},
|
||||
{"NPK_0", BIT(3)},
|
||||
{"D2D_NOC_1", BIT(4)},
|
||||
{"SBR8B2", BIT(5)},
|
||||
{"FUSE", BIT(6)},
|
||||
{"SBR16B0", BIT(7)},
|
||||
|
||||
{"PSF0", BIT(0)},
|
||||
{"XDCI", BIT(1)},
|
||||
{"EXI", BIT(2)},
|
||||
{"CSE", BIT(3)},
|
||||
{"KVMCC", BIT(4)},
|
||||
{"PMT", BIT(5)},
|
||||
{"CLINK", BIT(6)},
|
||||
{"PTIO", BIT(7)},
|
||||
|
||||
{"USBR0", BIT(0)},
|
||||
{"SUSRAM", BIT(1)},
|
||||
{"SMT1", BIT(2)},
|
||||
{"MPFPW1", BIT(3)},
|
||||
{"SMS2", BIT(4)},
|
||||
{"SMS1", BIT(5)},
|
||||
{"CSMERTC", BIT(6)},
|
||||
{"CSMEPSF", BIT(7)},
|
||||
|
||||
{"D2D_NOC_0", BIT(0)},
|
||||
{"ESE", BIT(1)},
|
||||
{"P2SB8B", BIT(2)},
|
||||
{"SBR16B7", BIT(3)},
|
||||
{"SBR16B3", BIT(4)},
|
||||
{"OSSE_SMT1", BIT(5)},
|
||||
{"D2D_DISP", BIT(6)},
|
||||
{"DBG_SBR", BIT(7)},
|
||||
|
||||
{"U3FPW1", BIT(0)},
|
||||
{"FIA_X", BIT(1)},
|
||||
{"PSF4", BIT(2)},
|
||||
{"CNVI", BIT(3)},
|
||||
{"UFSX2", BIT(4)},
|
||||
{"ENDBG", BIT(5)},
|
||||
{"DBC", BIT(6)},
|
||||
{"FIA_PG", BIT(7)},
|
||||
|
||||
{"D2D_IPU", BIT(0)},
|
||||
{"NPK1", BIT(1)},
|
||||
{"FIACPCB_X", BIT(2)},
|
||||
{"SBR8B4", BIT(3)},
|
||||
{"DBG_PSF", BIT(4)},
|
||||
{"PSF6", BIT(5)},
|
||||
{"UFSPW1", BIT(6)},
|
||||
{"FIA_U", BIT(7)},
|
||||
|
||||
{"PSF8", BIT(0)},
|
||||
{"SBR16B4", BIT(1)},
|
||||
{"SBR16B5", BIT(2)},
|
||||
{"FIACPCB_U", BIT(3)},
|
||||
{"TAM", BIT(4)},
|
||||
{"D2D_NOC_2", BIT(5)},
|
||||
{"TBTLSX", BIT(6)},
|
||||
{"THC0", BIT(7)},
|
||||
|
||||
{"THC1", BIT(0)},
|
||||
{"PMC_1", BIT(1)},
|
||||
{"SBR8B1", BIT(2)},
|
||||
{"TCSS", BIT(3)},
|
||||
{"DISP_PGA", BIT(4)},
|
||||
{"SBR16B1", BIT(5)},
|
||||
{"SBRG", BIT(6)},
|
||||
{"PSF5", BIT(7)},
|
||||
|
||||
{"P2SB16B", BIT(0)},
|
||||
{"ACE_0", BIT(1)},
|
||||
{"ACE_1", BIT(2)},
|
||||
{"ACE_2", BIT(3)},
|
||||
{"ACE_3", BIT(4)},
|
||||
{"ACE_4", BIT(5)},
|
||||
{"ACE_5", BIT(6)},
|
||||
{"ACE_6", BIT(7)},
|
||||
|
||||
{"ACE_7", BIT(0)},
|
||||
{"ACE_8", BIT(1)},
|
||||
{"ACE_9", BIT(2)},
|
||||
{"ACE_10", BIT(3)},
|
||||
{"FIACPCB_PG", BIT(4)},
|
||||
{"SBR16B6", BIT(5)},
|
||||
{"OSSE", BIT(6)},
|
||||
{"SBR8B0", BIT(7)},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map *ext_ptl_pcdp_pfear_map[] = {
|
||||
ptl_pcdp_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
|
||||
{"SATA", CNP_PMC_LTR_SATA},
|
||||
{"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE},
|
||||
{"XHCI", CNP_PMC_LTR_XHCI},
|
||||
{"SOUTHPORT_F", ADL_PMC_LTR_SPF},
|
||||
{"ME", CNP_PMC_LTR_ME},
|
||||
{"SATA1", CNP_PMC_LTR_EVA},
|
||||
{"SOUTHPORT_C", CNP_PMC_LTR_SPC},
|
||||
{"HD_AUDIO", CNP_PMC_LTR_AZ},
|
||||
{"CNV", CNP_PMC_LTR_CNV},
|
||||
{"LPSS", CNP_PMC_LTR_LPSS},
|
||||
{"SOUTHPORT_D", CNP_PMC_LTR_SPD},
|
||||
{"SOUTHPORT_E", CNP_PMC_LTR_SPE},
|
||||
{"SATA2", PTL_PMC_LTR_SATA2},
|
||||
{"ESPI", CNP_PMC_LTR_ESPI},
|
||||
{"SCC", CNP_PMC_LTR_SCC},
|
||||
{"ISH", CNP_PMC_LTR_ISH},
|
||||
{"UFSX2", CNP_PMC_LTR_UFSX2},
|
||||
{"EMMC", CNP_PMC_LTR_EMMC},
|
||||
{"WIGIG", ICL_PMC_LTR_WIGIG},
|
||||
{"THC0", TGL_PMC_LTR_THC0},
|
||||
{"THC1", TGL_PMC_LTR_THC1},
|
||||
{"SOUTHPORT_G", MTL_PMC_LTR_SPG},
|
||||
{"ESE", MTL_PMC_LTR_ESE},
|
||||
{"IOE_PMC", MTL_PMC_LTR_IOE_PMC},
|
||||
{"DMI3", ARL_PMC_LTR_DMI3},
|
||||
{"OSSE", LNL_PMC_LTR_OSSE},
|
||||
|
||||
/* Below two cannot be used for LTR_IGNORE */
|
||||
{"CURRENT_PLATFORM", PTL_PMC_LTR_CUR_PLT},
|
||||
{"AGGREGATED_SYSTEM", PTL_PMC_LTR_CUR_ASLT},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_clocksource_status_map[] = {
|
||||
{"AON2_OFF_STS", BIT(0), 1},
|
||||
{"AON3_OFF_STS", BIT(1), 0},
|
||||
{"AON4_OFF_STS", BIT(2), 1},
|
||||
{"AON5_OFF_STS", BIT(3), 1},
|
||||
{"AON1_OFF_STS", BIT(4), 0},
|
||||
{"XTAL_LVM_OFF_STS", BIT(5), 0},
|
||||
{"MPFPW1_0_PLL_OFF_STS", BIT(6), 1},
|
||||
{"USB3_PLL_OFF_STS", BIT(8), 1},
|
||||
{"AON3_SPL_OFF_STS", BIT(9), 1},
|
||||
{"MPFPW2_0_PLL_OFF_STS", BIT(12), 1},
|
||||
{"XTAL_AGGR_OFF_STS", BIT(17), 1},
|
||||
{"USB2_PLL_OFF_STS", BIT(18), 0},
|
||||
{"SAF_PLL_OFF_STS", BIT(19), 1},
|
||||
{"SE_TCSS_PLL_OFF_STS", BIT(20), 1},
|
||||
{"DDI_PLL_OFF_STS", BIT(21), 1},
|
||||
{"FILTER_PLL_OFF_STS", BIT(22), 1},
|
||||
{"ACE_PLL_OFF_STS", BIT(24), 0},
|
||||
{"FABRIC_PLL_OFF_STS", BIT(25), 1},
|
||||
{"SOC_PLL_OFF_STS", BIT(26), 1},
|
||||
{"REF_PLL_OFF_STS", BIT(28), 1},
|
||||
{"IMG_PLL_OFF_STS", BIT(29), 1},
|
||||
{"RTC_PLL_OFF_STS", BIT(31), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_power_gating_status_0_map[] = {
|
||||
{"PMC_PGD0_PG_STS", BIT(0), 0},
|
||||
{"FUSE_OSSE_PGD0_PG_STS", BIT(1), 0},
|
||||
{"ESPISPI_PGD0_PG_STS", BIT(2), 0},
|
||||
{"XHCI_PGD0_PG_STS", BIT(3), 1},
|
||||
{"SPA_PGD0_PG_STS", BIT(4), 1},
|
||||
{"SPB_PGD0_PG_STS", BIT(5), 1},
|
||||
{"MPFPW2_PGD0_PG_STS", BIT(6), 0},
|
||||
{"GBE_PGD0_PG_STS", BIT(7), 1},
|
||||
{"SBR16B20_PGD0_PG_STS", BIT(8), 0},
|
||||
{"SBR8B20_PGD0_PG_STS", BIT(9), 0},
|
||||
{"SBR16B21_PGD0_PG_STS", BIT(10), 0},
|
||||
{"DBG_PGD0_PG_STS", BIT(11), 0},
|
||||
{"OSSE_HOTHAM_PGD0_PG_STS", BIT(12), 1},
|
||||
{"D2D_DISP_PGD1_PG_STS", BIT(13), 1},
|
||||
{"LPSS_PGD0_PG_STS", BIT(14), 1},
|
||||
{"LPC_PGD0_PG_STS", BIT(15), 0},
|
||||
{"SMB_PGD0_PG_STS", BIT(16), 0},
|
||||
{"ISH_PGD0_PG_STS", BIT(17), 0},
|
||||
{"SBR16B2_PGD0_PG_STS", BIT(18), 0},
|
||||
{"NPK_PGD0_PG_STS", BIT(19), 0},
|
||||
{"D2D_NOC_PGD1_PG_STS", BIT(20), 1},
|
||||
{"SBR8B2_PGD0_PG_STS", BIT(21), 0},
|
||||
{"FUSE_PGD0_PG_STS", BIT(22), 0},
|
||||
{"SBR16B0_PGD0_PG_STS", BIT(23), 0},
|
||||
{"PSF0_PGD0_PG_STS", BIT(24), 0},
|
||||
{"XDCI_PGD0_PG_STS", BIT(25), 1},
|
||||
{"EXI_PGD0_PG_STS", BIT(26), 0},
|
||||
{"CSE_PGD0_PG_STS", BIT(27), 1},
|
||||
{"KVMCC_PGD0_PG_STS", BIT(28), 1},
|
||||
{"PMT_PGD0_PG_STS", BIT(29), 1},
|
||||
{"CLINK_PGD0_PG_STS", BIT(30), 1},
|
||||
{"PTIO_PGD0_PG_STS", BIT(31), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_power_gating_status_1_map[] = {
|
||||
{"USBR0_PGD0_PG_STS", BIT(0), 1},
|
||||
{"SUSRAM_PGD0_PG_STS", BIT(1), 1},
|
||||
{"SMT1_PGD0_PG_STS", BIT(2), 1},
|
||||
{"MPFPW1_PGD0_PG_STS", BIT(3), 0},
|
||||
{"SMS2_PGD0_PG_STS", BIT(4), 1},
|
||||
{"SMS1_PGD0_PG_STS", BIT(5), 1},
|
||||
{"CSMERTC_PGD0_PG_STS", BIT(6), 0},
|
||||
{"CSMEPSF_PGD0_PG_STS", BIT(7), 0},
|
||||
{"D2D_NOC_PGD0_PG_STS", BIT(8), 0},
|
||||
{"ESE_PGD0_PG_STS", BIT(9), 1},
|
||||
{"P2SB8B_PGD0_PG_STS", BIT(10), 1},
|
||||
{"SBR16B7_PGD0_PG_STS", BIT(11), 0},
|
||||
{"SBR16B3_PGD0_PG_STS", BIT(12), 0},
|
||||
{"OSSE_SMT1_PGD0_PG_STS", BIT(13), 1},
|
||||
{"D2D_DISP_PGD0_PG_STS", BIT(14), 1},
|
||||
{"DBG_SBR_PGD0_PG_STS", BIT(15), 0},
|
||||
{"U3FPW1_PGD0_PG_STS", BIT(16), 0},
|
||||
{"FIA_X_PGD0_PG_STS", BIT(17), 0},
|
||||
{"PSF4_PGD0_PG_STS", BIT(18), 0},
|
||||
{"CNVI_PGD0_PG_STS", BIT(19), 0},
|
||||
{"UFSX2_PGD0_PG_STS", BIT(20), 1},
|
||||
{"ENDBG_PGD0_PG_STS", BIT(21), 0},
|
||||
{"DBC_PGD0_PG_STS", BIT(22), 0},
|
||||
{"FIA_PG_PGD0_PG_STS", BIT(23), 0},
|
||||
{"D2D_IPU_PGD0_PG_STS", BIT(24), 1},
|
||||
{"NPK_PGD1_PG_STS", BIT(25), 0},
|
||||
{"FIACPCB_X_PGD0_PG_STS", BIT(26), 0},
|
||||
{"SBR8B4_PGD0_PG_STS", BIT(27), 0},
|
||||
{"DBG_PSF_PGD0_PG_STS", BIT(28), 0},
|
||||
{"PSF6_PGD0_PG_STS", BIT(29), 0},
|
||||
{"UFSPW1_PGD0_PG_STS", BIT(30), 0},
|
||||
{"FIA_U_PGD0_PG_STS", BIT(31), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_power_gating_status_2_map[] = {
|
||||
{"PSF8_PGD0_PG_STS", BIT(0), 0},
|
||||
{"SBR16B4_PGD0_PG_STS", BIT(1), 0},
|
||||
{"SBR16B5_PGD0_PG_STS", BIT(2), 0},
|
||||
{"FIACPCB_U_PGD0_PG_STS", BIT(3), 0},
|
||||
{"TAM_PGD0_PG_STS", BIT(4), 1},
|
||||
{"D2D_NOC_PGD0_PG_STS", BIT(5), 1},
|
||||
{"TBTLSX_PGD0_PG_STS", BIT(6), 1},
|
||||
{"THC0_PGD0_PG_STS", BIT(7), 1},
|
||||
{"THC1_PGD0_PG_STS", BIT(8), 1},
|
||||
{"PMC_PGD1_PG_STS", BIT(9), 0},
|
||||
{"SBR8B1_PGD0_PG_STS", BIT(10), 0},
|
||||
{"TCSS_PGD0_PG_STS", BIT(11), 0},
|
||||
{"DISP_PGA_PGD0_PG_STS", BIT(12), 0},
|
||||
{"SBR16B1_PGD0_PG_STS", BIT(13), 0},
|
||||
{"SBRG_PGD0_PG_STS", BIT(14), 0},
|
||||
{"PSF5_PGD0_PG_STS", BIT(15), 0},
|
||||
{"P2SB16B_PGD0_PG_STS", BIT(16), 1},
|
||||
{"ACE_PGD0_PG_STS", BIT(17), 0},
|
||||
{"ACE_PGD1_PG_STS", BIT(18), 0},
|
||||
{"ACE_PGD2_PG_STS", BIT(19), 0},
|
||||
{"ACE_PGD3_PG_STS", BIT(20), 0},
|
||||
{"ACE_PGD4_PG_STS", BIT(21), 0},
|
||||
{"ACE_PGD5_PG_STS", BIT(22), 0},
|
||||
{"ACE_PGD6_PG_STS", BIT(23), 0},
|
||||
{"ACE_PGD7_PG_STS", BIT(24), 0},
|
||||
{"ACE_PGD8_PG_STS", BIT(25), 0},
|
||||
{"ACE_PGD9_PG_STS", BIT(26), 0},
|
||||
{"ACE_PGD10_PG_STS", BIT(27), 0},
|
||||
{"FIACPCB_PG_PGD0_PG_STS", BIT(28), 0},
|
||||
{"SBR16B6_PGD0_PG_STS", BIT(29), 0},
|
||||
{"OSSE_PGD0_PG_STS", BIT(30), 1},
|
||||
{"SBR8B0_PGD0_PG_STS", BIT(31), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_d3_status_0_map[] = {
|
||||
{"LPSS_D3_STS", BIT(3), 1},
|
||||
{"XDCI_D3_STS", BIT(4), 1},
|
||||
{"XHCI_D3_STS", BIT(5), 1},
|
||||
{"OSSE_D3_STS", BIT(6), 0},
|
||||
{"SPA_D3_STS", BIT(12), 0},
|
||||
{"SPB_D3_STS", BIT(13), 0},
|
||||
{"ESPISPI_D3_STS", BIT(18), 0},
|
||||
{"PSTH_D3_STS", BIT(21), 0},
|
||||
{"OSSE_SMT1_D3_STS", BIT(30), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_d3_status_1_map[] = {
|
||||
{"GBE_D3_STS", BIT(19), 0},
|
||||
{"ITSS_D3_STS", BIT(23), 0},
|
||||
{"CNVI_D3_STS", BIT(27), 0},
|
||||
{"UFSX2_D3_STS", BIT(28), 1},
|
||||
{"OSSE_HOTHAM_D3_STS", BIT(29), 0},
|
||||
{"ESE_D3_STS", BIT(30), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_d3_status_2_map[] = {
|
||||
{"CSMERTC_D3_STS", BIT(1), 0},
|
||||
{"SUSRAM_D3_STS", BIT(2), 0},
|
||||
{"CSE_D3_STS", BIT(4), 0},
|
||||
{"KVMCC_D3_STS", BIT(5), 0},
|
||||
{"USBR0_D3_STS", BIT(6), 0},
|
||||
{"ISH_D3_STS", BIT(7), 0},
|
||||
{"SMT1_D3_STS", BIT(8), 0},
|
||||
{"SMT2_D3_STS", BIT(9), 0},
|
||||
{"SMT3_D3_STS", BIT(10), 0},
|
||||
{"OSSE_SMT2_D3_STS", BIT(12), 0},
|
||||
{"CLINK_D3_STS", BIT(14), 0},
|
||||
{"PTIO_D3_STS", BIT(16), 0},
|
||||
{"PMT_D3_STS", BIT(17), 0},
|
||||
{"SMS1_D3_STS", BIT(18), 0},
|
||||
{"SMS2_D3_STS", BIT(19), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_d3_status_3_map[] = {
|
||||
{"THC0_D3_STS", BIT(14), 1},
|
||||
{"THC1_D3_STS", BIT(15), 1},
|
||||
{"OSSE_SMT3_D3_STS", BIT(18), 0},
|
||||
{"ACE_D3_STS", BIT(23), 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_vnn_req_status_0_map[] = {
|
||||
{"LPSS_VNN_REQ_STS", BIT(3), 1},
|
||||
{"OSSE_VNN_REQ_STS", BIT(6), 1},
|
||||
{"ESPISPI_VNN_REQ_STS", BIT(18), 1},
|
||||
{"OSSE_SMT1_VNN_REQ_STS", BIT(30), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_vnn_req_status_1_map[] = {
|
||||
{"NPK_VNN_REQ_STS", BIT(4), 1},
|
||||
{"DFXAGG_VNN_REQ_STS", BIT(8), 0},
|
||||
{"EXI_VNN_REQ_STS", BIT(9), 1},
|
||||
{"P2D_VNN_REQ_STS", BIT(18), 1},
|
||||
{"GBE_VNN_REQ_STS", BIT(19), 1},
|
||||
{"SMB_VNN_REQ_STS", BIT(25), 1},
|
||||
{"LPC_VNN_REQ_STS", BIT(26), 0},
|
||||
{"ESE_VNN_REQ_STS", BIT(30), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_vnn_req_status_2_map[] = {
|
||||
{"CSMERTC_VNN_REQ_STS", BIT(1), 1},
|
||||
{"CSE_VNN_REQ_STS", BIT(4), 1},
|
||||
{"ISH_VNN_REQ_STS", BIT(7), 1},
|
||||
{"SMT1_VNN_REQ_STS", BIT(8), 1},
|
||||
{"CLINK_VNN_REQ_STS", BIT(14), 1},
|
||||
{"SMS1_VNN_REQ_STS", BIT(18), 1},
|
||||
{"SMS2_VNN_REQ_STS", BIT(19), 1},
|
||||
{"GPIOCOM4_VNN_REQ_STS", BIT(20), 1},
|
||||
{"GPIOCOM3_VNN_REQ_STS", BIT(21), 1},
|
||||
{"GPIOCOM1_VNN_REQ_STS", BIT(23), 1},
|
||||
{"GPIOCOM0_VNN_REQ_STS", BIT(24), 1},
|
||||
{"DISP_SHIM_VNN_REQ_STS", BIT(26), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_vnn_req_status_3_map[] = {
|
||||
{"DTS0_VNN_REQ_STS", BIT(7), 0},
|
||||
{"GPIOCOM5_VNN_REQ_STS", BIT(11), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_vnn_misc_status_map[] = {
|
||||
{"CPU_C10_REQ_STS", BIT(0), 0},
|
||||
{"TS_OFF_REQ_STS", BIT(1), 0},
|
||||
{"PNDE_MET_REQ_STS", BIT(2), 1},
|
||||
{"PG5_PMA0_REQ_STS", BIT(3), 0},
|
||||
{"FW_THROTTLE_ALLOWED_REQ_STS", BIT(4), 0},
|
||||
{"VNN_SOC_REQ_STS", BIT(6), 1},
|
||||
{"ISH_VNNAON_REQ_STS", BIT(7), 0},
|
||||
{"D2D_NOC_CFI_QACTIVE_REQ_STS", BIT(8), 1},
|
||||
{"D2D_NOC_GPSB_QACTIVE_REQ_STS", BIT(9), 1},
|
||||
{"D2D_IPU_QACTIVE_REQ_STS", BIT(10), 1},
|
||||
{"PLT_GREATER_REQ_STS", BIT(11), 1},
|
||||
{"ALL_SBR_IDLE_REQ_STS", BIT(12), 0},
|
||||
{"PMC_IDLE_FB_OCP_REQ_STS", BIT(13), 0},
|
||||
{"PM_SYNC_STATES_REQ_STS", BIT(14), 0},
|
||||
{"EA_REQ_STS", BIT(15), 0},
|
||||
{"MPHY_CORE_OFF_REQ_STS", BIT(16), 0},
|
||||
{"BRK_EV_EN_REQ_STS", BIT(17), 0},
|
||||
{"AUTO_DEMO_EN_REQ_STS", BIT(18), 0},
|
||||
{"ITSS_CLK_SRC_REQ_STS", BIT(19), 1},
|
||||
{"ARC_IDLE_REQ_STS", BIT(21), 0},
|
||||
{"PG5_PMA1_REQ_STS", BIT(22), 0},
|
||||
{"FIA_DEEP_PM_REQ_STS", BIT(23), 0},
|
||||
{"XDCI_ATTACHED_REQ_STS", BIT(24), 1},
|
||||
{"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25), 0},
|
||||
{"D2D_DISP_DDI_QACTIVE_REQ_STS", BIT(26), 1},
|
||||
{"PRE_WAKE0_REQ_STS", BIT(27), 1},
|
||||
{"PRE_WAKE1_REQ_STS", BIT(28), 1},
|
||||
{"PRE_WAKE2_REQ_STS", BIT(29), 1},
|
||||
{"D2D_DISP_EDP_QACTIVE_REQ_STS", BIT(31), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_signal_status_map[] = {
|
||||
{"LSX_Wake0_STS", BIT(0), 0},
|
||||
{"LSX_Wake1_STS", BIT(1), 0},
|
||||
{"LSX_Wake2_STS", BIT(2), 0},
|
||||
{"LSX_Wake3_STS", BIT(3), 0},
|
||||
{"LSX_Wake4_STS", BIT(4), 0},
|
||||
{"LSX_Wake5_STS", BIT(5), 0},
|
||||
{"LSX_Wake6_STS", BIT(6), 0},
|
||||
{"LSX_Wake7_STS", BIT(7), 0},
|
||||
{"LPSS_Wake0_STS", BIT(8), 1},
|
||||
{"LPSS_Wake1_STS", BIT(9), 1},
|
||||
{"Int_Timer_SS_Wake0_STS", BIT(10), 1},
|
||||
{"Int_Timer_SS_Wake1_STS", BIT(11), 1},
|
||||
{"Int_Timer_SS_Wake2_STS", BIT(12), 1},
|
||||
{"Int_Timer_SS_Wake3_STS", BIT(13), 1},
|
||||
{"Int_Timer_SS_Wake4_STS", BIT(14), 1},
|
||||
{"Int_Timer_SS_Wake5_STS", BIT(15), 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map ptl_pcdp_rsc_status_map[] = {
|
||||
{"Memory", 0, 1},
|
||||
{"PSF0", 0, 1},
|
||||
{"PSF4", 0, 1},
|
||||
{"PSF5", 0, 1},
|
||||
{"PSF6", 0, 1},
|
||||
{"PSF8", 0, 1},
|
||||
{"SAF_CFI_LINK", 0, 1},
|
||||
{"SB", 0, 1},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map *ptl_pcdp_lpm_maps[] = {
|
||||
ptl_pcdp_clocksource_status_map,
|
||||
ptl_pcdp_power_gating_status_0_map,
|
||||
ptl_pcdp_power_gating_status_1_map,
|
||||
ptl_pcdp_power_gating_status_2_map,
|
||||
ptl_pcdp_d3_status_0_map,
|
||||
ptl_pcdp_d3_status_1_map,
|
||||
ptl_pcdp_d3_status_2_map,
|
||||
ptl_pcdp_d3_status_3_map,
|
||||
ptl_pcdp_vnn_req_status_0_map,
|
||||
ptl_pcdp_vnn_req_status_1_map,
|
||||
ptl_pcdp_vnn_req_status_2_map,
|
||||
ptl_pcdp_vnn_req_status_3_map,
|
||||
ptl_pcdp_vnn_misc_status_map,
|
||||
ptl_pcdp_signal_status_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map *ptl_pcdp_blk_maps[] = {
|
||||
ptl_pcdp_power_gating_status_0_map,
|
||||
ptl_pcdp_power_gating_status_1_map,
|
||||
ptl_pcdp_power_gating_status_2_map,
|
||||
ptl_pcdp_rsc_status_map,
|
||||
ptl_pcdp_vnn_req_status_0_map,
|
||||
ptl_pcdp_vnn_req_status_1_map,
|
||||
ptl_pcdp_vnn_req_status_2_map,
|
||||
ptl_pcdp_vnn_req_status_3_map,
|
||||
ptl_pcdp_d3_status_0_map,
|
||||
ptl_pcdp_d3_status_1_map,
|
||||
ptl_pcdp_d3_status_2_map,
|
||||
ptl_pcdp_d3_status_3_map,
|
||||
ptl_pcdp_clocksource_status_map,
|
||||
ptl_pcdp_vnn_misc_status_map,
|
||||
ptl_pcdp_signal_status_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_reg_map ptl_pcdp_reg_map = {
|
||||
.pfear_sts = ext_ptl_pcdp_pfear_map,
|
||||
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
|
||||
.slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
|
||||
.ltr_show_sts = ptl_pcdp_ltr_show_map,
|
||||
.msr_sts = msr_map,
|
||||
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
|
||||
.regmap_length = PTL_PCD_PMC_MMIO_REG_LEN,
|
||||
.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
|
||||
.ppfear_buckets = LNL_PPFEAR_NUM_ENTRIES,
|
||||
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
|
||||
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
|
||||
.lpm_num_maps = PTL_LPM_NUM_MAPS,
|
||||
.ltr_ignore_max = LNL_NUM_IP_IGN_ALLOWED,
|
||||
.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
|
||||
.etr3_offset = ETR3_OFFSET,
|
||||
.lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET,
|
||||
.lpm_priority_offset = MTL_LPM_PRI_OFFSET,
|
||||
.lpm_en_offset = MTL_LPM_EN_OFFSET,
|
||||
.lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET,
|
||||
.lpm_sts = ptl_pcdp_lpm_maps,
|
||||
.lpm_status_offset = MTL_LPM_STATUS_OFFSET,
|
||||
.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
|
||||
.s0ix_blocker_maps = ptl_pcdp_blk_maps,
|
||||
.s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET,
|
||||
};
|
||||
|
||||
#define PTL_NPU_PCI_DEV 0xb03e
|
||||
#define PTL_IPU_PCI_DEV 0xb05d
|
||||
|
||||
/*
|
||||
* Set power state of select devices that do not have drivers to D3
|
||||
* so that they do not block Package C entry.
|
||||
*/
|
||||
static void ptl_d3_fixup(void)
|
||||
{
|
||||
pmc_core_set_device_d3(PTL_IPU_PCI_DEV);
|
||||
pmc_core_set_device_d3(PTL_NPU_PCI_DEV);
|
||||
}
|
||||
|
||||
static int ptl_resume(struct pmc_dev *pmcdev)
|
||||
{
|
||||
ptl_d3_fixup();
|
||||
return cnl_resume(pmcdev);
|
||||
}
|
||||
|
||||
static int ptl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
ptl_d3_fixup();
|
||||
return generic_core_init(pmcdev, pmc_dev_info);
|
||||
}
|
||||
|
||||
struct pmc_dev_info ptl_pmc_dev = {
|
||||
.map = &ptl_pcdp_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = ptl_resume,
|
||||
.init = ptl_core_init,
|
||||
};
|
||||
|
|
@ -8,9 +8,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
const struct pmc_bit_map spt_pll_map[] = {
|
||||
static const struct pmc_bit_map spt_pll_map[] = {
|
||||
{"MIPI PLL", SPT_PMC_BIT_MPHY_CMN_LANE0},
|
||||
{"GEN2 USB2PCIE2 PLL", SPT_PMC_BIT_MPHY_CMN_LANE1},
|
||||
{"DMIPCIE3 PLL", SPT_PMC_BIT_MPHY_CMN_LANE2},
|
||||
|
|
@ -18,7 +20,7 @@ const struct pmc_bit_map spt_pll_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map spt_mphy_map[] = {
|
||||
static const struct pmc_bit_map spt_mphy_map[] = {
|
||||
{"MPHY CORE LANE 0", SPT_PMC_BIT_MPHY_LANE0},
|
||||
{"MPHY CORE LANE 1", SPT_PMC_BIT_MPHY_LANE1},
|
||||
{"MPHY CORE LANE 2", SPT_PMC_BIT_MPHY_LANE2},
|
||||
|
|
@ -38,7 +40,7 @@ const struct pmc_bit_map spt_mphy_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map spt_pfear_map[] = {
|
||||
static const struct pmc_bit_map spt_pfear_map[] = {
|
||||
{"PMC", SPT_PMC_BIT_PMC},
|
||||
{"OPI-DMI", SPT_PMC_BIT_OPI},
|
||||
{"SPI / eSPI", SPT_PMC_BIT_SPI},
|
||||
|
|
@ -82,7 +84,7 @@ const struct pmc_bit_map spt_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_spt_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_spt_pfear_map[] = {
|
||||
/*
|
||||
* Check intel_pmc_core_ids[] users of spt_reg_map for
|
||||
* a list of core SoCs using this.
|
||||
|
|
@ -91,7 +93,7 @@ const struct pmc_bit_map *ext_spt_pfear_map[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map spt_ltr_show_map[] = {
|
||||
static const struct pmc_bit_map spt_ltr_show_map[] = {
|
||||
{"SOUTHPORT_A", SPT_PMC_LTR_SPA},
|
||||
{"SOUTHPORT_B", SPT_PMC_LTR_SPB},
|
||||
{"SATA", SPT_PMC_LTR_SATA},
|
||||
|
|
@ -116,7 +118,7 @@ const struct pmc_bit_map spt_ltr_show_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_reg_map spt_reg_map = {
|
||||
static const struct pmc_reg_map spt_reg_map = {
|
||||
.pfear_sts = ext_spt_pfear_map,
|
||||
.mphy_sts = spt_mphy_map,
|
||||
.pll_sts = spt_pll_map,
|
||||
|
|
@ -134,18 +136,25 @@ const struct pmc_reg_map spt_reg_map = {
|
|||
.pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,
|
||||
};
|
||||
|
||||
int spt_core_init(struct pmc_dev *pmcdev)
|
||||
static const struct pci_device_id spt_pmc_pci_id[] = {
|
||||
{ PCI_VDEVICE(INTEL, SPT_PMC_PCI_DEVICE_ID) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int spt_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
|
||||
int ret;
|
||||
/*
|
||||
* Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here
|
||||
* Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap
|
||||
* in this case.
|
||||
*/
|
||||
if (!pci_dev_present(spt_pmc_pci_id))
|
||||
return generic_core_init(pmcdev, &cnp_pmc_dev);
|
||||
|
||||
pmc->map = &spt_reg_map;
|
||||
|
||||
ret = get_primary_reg_base(pmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
|
||||
return ret;
|
||||
return generic_core_init(pmcdev, pmc_dev_info);
|
||||
}
|
||||
|
||||
struct pmc_dev_info spt_pmc_dev = {
|
||||
.map = &spt_reg_map,
|
||||
.init = spt_core_init,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ enum pch_type {
|
|||
PCH_LP
|
||||
};
|
||||
|
||||
const struct pmc_bit_map tgl_pfear_map[] = {
|
||||
static const struct pmc_bit_map tgl_pfear_map[] = {
|
||||
{"PSF9", BIT(0)},
|
||||
{"RES_66", BIT(1)},
|
||||
{"RES_67", BIT(2)},
|
||||
|
|
@ -29,7 +29,7 @@ const struct pmc_bit_map tgl_pfear_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *ext_tgl_pfear_map[] = {
|
||||
static const struct pmc_bit_map *ext_tgl_pfear_map[] = {
|
||||
/*
|
||||
* Check intel_pmc_core_ids[] users of tgl_reg_map for
|
||||
* a list of core SoCs using this.
|
||||
|
|
@ -39,7 +39,7 @@ const struct pmc_bit_map *ext_tgl_pfear_map[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_bit_map tgl_clocksource_status_map[] = {
|
||||
static const struct pmc_bit_map tgl_clocksource_status_map[] = {
|
||||
{"USB2PLL_OFF_STS", BIT(18)},
|
||||
{"PCIe/USB3.1_Gen2PLL_OFF_STS", BIT(19)},
|
||||
{"PCIe_Gen3PLL_OFF_STS", BIT(20)},
|
||||
|
|
@ -55,7 +55,7 @@ const struct pmc_bit_map tgl_clocksource_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map tgl_power_gating_status_map[] = {
|
||||
static const struct pmc_bit_map tgl_power_gating_status_map[] = {
|
||||
{"CSME_PG_STS", BIT(0)},
|
||||
{"SATA_PG_STS", BIT(1)},
|
||||
{"xHCI_PG_STS", BIT(2)},
|
||||
|
|
@ -83,7 +83,7 @@ const struct pmc_bit_map tgl_power_gating_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map tgl_d3_status_map[] = {
|
||||
static const struct pmc_bit_map tgl_d3_status_map[] = {
|
||||
{"ADSP_D3_STS", BIT(0)},
|
||||
{"SATA_D3_STS", BIT(1)},
|
||||
{"xHCI0_D3_STS", BIT(2)},
|
||||
|
|
@ -98,7 +98,7 @@ const struct pmc_bit_map tgl_d3_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map tgl_vnn_req_status_map[] = {
|
||||
static const struct pmc_bit_map tgl_vnn_req_status_map[] = {
|
||||
{"GPIO_COM0_VNN_REQ_STS", BIT(1)},
|
||||
{"GPIO_COM1_VNN_REQ_STS", BIT(2)},
|
||||
{"GPIO_COM2_VNN_REQ_STS", BIT(3)},
|
||||
|
|
@ -123,7 +123,7 @@ const struct pmc_bit_map tgl_vnn_req_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map tgl_vnn_misc_status_map[] = {
|
||||
static const struct pmc_bit_map tgl_vnn_misc_status_map[] = {
|
||||
{"CPU_C10_REQ_STS_0", BIT(0)},
|
||||
{"PCIe_LPM_En_REQ_STS_3", BIT(3)},
|
||||
{"ITH_REQ_STS_5", BIT(5)},
|
||||
|
|
@ -175,7 +175,7 @@ const struct pmc_bit_map tgl_signal_status_map[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
const struct pmc_bit_map *tgl_lpm_maps[] = {
|
||||
static const struct pmc_bit_map *tgl_lpm_maps[] = {
|
||||
tgl_clocksource_status_map,
|
||||
tgl_power_gating_status_map,
|
||||
tgl_d3_status_map,
|
||||
|
|
@ -185,7 +185,7 @@ const struct pmc_bit_map *tgl_lpm_maps[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const struct pmc_reg_map tgl_reg_map = {
|
||||
static const struct pmc_reg_map tgl_reg_map = {
|
||||
.pfear_sts = ext_tgl_pfear_map,
|
||||
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
|
||||
.slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
|
||||
|
|
@ -210,7 +210,7 @@ const struct pmc_reg_map tgl_reg_map = {
|
|||
.etr3_offset = ETR3_OFFSET,
|
||||
};
|
||||
|
||||
const struct pmc_reg_map tgl_h_reg_map = {
|
||||
static const struct pmc_reg_map tgl_h_reg_map = {
|
||||
.pfear_sts = ext_tgl_pfear_map,
|
||||
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
|
||||
.slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
|
||||
|
|
@ -285,35 +285,28 @@ void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev)
|
|||
ACPI_FREE(out_obj);
|
||||
}
|
||||
|
||||
int tgl_l_core_init(struct pmc_dev *pmcdev)
|
||||
static int tgl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info)
|
||||
{
|
||||
return tgl_core_generic_init(pmcdev, PCH_LP);
|
||||
}
|
||||
|
||||
int tgl_core_init(struct pmc_dev *pmcdev)
|
||||
{
|
||||
return tgl_core_generic_init(pmcdev, PCH_H);
|
||||
}
|
||||
|
||||
int tgl_core_generic_init(struct pmc_dev *pmcdev, int pch_tp)
|
||||
{
|
||||
struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN];
|
||||
int ret;
|
||||
|
||||
if (pch_tp == PCH_H)
|
||||
pmc->map = &tgl_h_reg_map;
|
||||
else
|
||||
pmc->map = &tgl_reg_map;
|
||||
|
||||
pmcdev->suspend = cnl_suspend;
|
||||
pmcdev->resume = cnl_resume;
|
||||
|
||||
ret = get_primary_reg_base(pmc);
|
||||
ret = generic_core_init(pmcdev, pmc_dev_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmc_core_get_low_power_modes(pmcdev);
|
||||
pmc_core_get_tgl_lpm_reqs(pmcdev->pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pmc_dev_info tgl_l_pmc_dev = {
|
||||
.map = &tgl_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = cnl_resume,
|
||||
.init = tgl_core_init,
|
||||
};
|
||||
|
||||
struct pmc_dev_info tgl_pmc_dev = {
|
||||
.map = &tgl_h_reg_map,
|
||||
.suspend = cnl_suspend,
|
||||
.resume = cnl_resume,
|
||||
.init = tgl_core_init,
|
||||
};
|
||||
|
|
|
|||
212
drivers/platform/x86/lenovo-wmi-hotkey-utilities.c
Normal file
212
drivers/platform/x86/lenovo-wmi-hotkey-utilities.c
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Lenovo Super Hotkey Utility WMI extras driver for Ideapad laptop
|
||||
*
|
||||
* Copyright (C) 2025 Lenovo
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/dev_printk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/wmi.h>
|
||||
|
||||
/* Lenovo Super Hotkey WMI GUIDs */
|
||||
#define LUD_WMI_METHOD_GUID "CE6C0974-0407-4F50-88BA-4FC3B6559AD8"
|
||||
|
||||
/* Lenovo Utility Data WMI method_id */
|
||||
#define WMI_LUD_GET_SUPPORT 1
|
||||
#define WMI_LUD_SET_FEATURE 2
|
||||
|
||||
#define WMI_LUD_GET_MICMUTE_LED_VER 20
|
||||
#define WMI_LUD_GET_AUDIOMUTE_LED_VER 26
|
||||
|
||||
#define WMI_LUD_SUPPORT_MICMUTE_LED_VER 25
|
||||
#define WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER 27
|
||||
|
||||
/* Input parameters to mute/unmute audio LED and Mic LED */
|
||||
struct wmi_led_args {
|
||||
u8 id;
|
||||
u8 subid;
|
||||
u16 value;
|
||||
};
|
||||
|
||||
/* Values of input parameters to SetFeature of audio LED and Mic LED */
|
||||
enum hotkey_set_feature {
|
||||
MIC_MUTE_LED_ON = 1,
|
||||
MIC_MUTE_LED_OFF = 2,
|
||||
AUDIO_MUTE_LED_ON = 4,
|
||||
AUDIO_MUTE_LED_OFF = 5,
|
||||
};
|
||||
|
||||
#define LSH_ACPI_LED_MAX 2
|
||||
|
||||
struct lenovo_super_hotkey_wmi_private {
|
||||
struct led_classdev cdev[LSH_ACPI_LED_MAX];
|
||||
struct wmi_device *led_wdev;
|
||||
};
|
||||
|
||||
enum mute_led_type {
|
||||
MIC_MUTE,
|
||||
AUDIO_MUTE,
|
||||
};
|
||||
|
||||
static int lsh_wmi_mute_led_set(enum mute_led_type led_type, struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
|
||||
{
|
||||
struct lenovo_super_hotkey_wmi_private *wpriv = container_of(led_cdev,
|
||||
struct lenovo_super_hotkey_wmi_private, cdev[led_type]);
|
||||
struct wmi_led_args led_arg = {0, 0, 0};
|
||||
struct acpi_buffer input;
|
||||
acpi_status status;
|
||||
|
||||
switch (led_type) {
|
||||
case MIC_MUTE:
|
||||
led_arg.id = brightness == LED_ON ? MIC_MUTE_LED_ON : MIC_MUTE_LED_OFF;
|
||||
break;
|
||||
case AUDIO_MUTE:
|
||||
led_arg.id = brightness == LED_ON ? AUDIO_MUTE_LED_ON : AUDIO_MUTE_LED_OFF;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
input.length = sizeof(led_arg);
|
||||
input.pointer = &led_arg;
|
||||
status = wmidev_evaluate_method(wpriv->led_wdev, 0, WMI_LUD_SET_FEATURE, &input, NULL);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lsh_wmi_audiomute_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
|
||||
{
|
||||
return lsh_wmi_mute_led_set(AUDIO_MUTE, led_cdev, brightness);
|
||||
}
|
||||
|
||||
static int lsh_wmi_micmute_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
return lsh_wmi_mute_led_set(MIC_MUTE, led_cdev, brightness);
|
||||
}
|
||||
|
||||
static int lenovo_super_hotkey_wmi_led_init(enum mute_led_type led_type, struct device *dev)
|
||||
{
|
||||
struct lenovo_super_hotkey_wmi_private *wpriv = dev_get_drvdata(dev);
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_buffer input;
|
||||
int led_version, err = 0;
|
||||
unsigned int wmiarg;
|
||||
acpi_status status;
|
||||
|
||||
switch (led_type) {
|
||||
case MIC_MUTE:
|
||||
wmiarg = WMI_LUD_GET_MICMUTE_LED_VER;
|
||||
break;
|
||||
case AUDIO_MUTE:
|
||||
wmiarg = WMI_LUD_GET_AUDIOMUTE_LED_VER;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
input.length = sizeof(wmiarg);
|
||||
input.pointer = &wmiarg;
|
||||
status = wmidev_evaluate_method(wpriv->led_wdev, 0, WMI_LUD_GET_SUPPORT, &input, &output);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
union acpi_object *obj __free(kfree) = output.pointer;
|
||||
if (obj && obj->type == ACPI_TYPE_INTEGER)
|
||||
led_version = obj->integer.value;
|
||||
else
|
||||
return -EIO;
|
||||
|
||||
wpriv->cdev[led_type].max_brightness = LED_ON;
|
||||
wpriv->cdev[led_type].flags = LED_CORE_SUSPENDRESUME;
|
||||
|
||||
switch (led_type) {
|
||||
case MIC_MUTE:
|
||||
if (led_version != WMI_LUD_SUPPORT_MICMUTE_LED_VER)
|
||||
return -EIO;
|
||||
|
||||
wpriv->cdev[led_type].name = "platform::micmute";
|
||||
wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_micmute_led_set;
|
||||
wpriv->cdev[led_type].default_trigger = "audio-micmute";
|
||||
break;
|
||||
case AUDIO_MUTE:
|
||||
if (led_version != WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER)
|
||||
return -EIO;
|
||||
|
||||
wpriv->cdev[led_type].name = "platform::mute";
|
||||
wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_audiomute_led_set;
|
||||
wpriv->cdev[led_type].default_trigger = "audio-mute";
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Unknown LED type %d\n", led_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = devm_led_classdev_register(dev, &wpriv->cdev[led_type]);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "Could not register mute LED %d : %d\n", led_type, err);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lenovo_super_hotkey_wmi_leds_setup(struct device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = lenovo_super_hotkey_wmi_led_init(MIC_MUTE, dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = lenovo_super_hotkey_wmi_led_init(AUDIO_MUTE, dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lenovo_super_hotkey_wmi_probe(struct wmi_device *wdev, const void *context)
|
||||
{
|
||||
struct lenovo_super_hotkey_wmi_private *wpriv;
|
||||
|
||||
wpriv = devm_kzalloc(&wdev->dev, sizeof(*wpriv), GFP_KERNEL);
|
||||
if (!wpriv)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&wdev->dev, wpriv);
|
||||
wpriv->led_wdev = wdev;
|
||||
return lenovo_super_hotkey_wmi_leds_setup(&wdev->dev);
|
||||
}
|
||||
|
||||
static const struct wmi_device_id lenovo_super_hotkey_wmi_id_table[] = {
|
||||
{ LUD_WMI_METHOD_GUID, NULL }, /* Utility data */
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(wmi, lenovo_super_hotkey_wmi_id_table);
|
||||
|
||||
static struct wmi_driver lenovo_wmi_hotkey_utilities_driver = {
|
||||
.driver = {
|
||||
.name = "lenovo_wmi_hotkey_utilities",
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS
|
||||
},
|
||||
.id_table = lenovo_super_hotkey_wmi_id_table,
|
||||
.probe = lenovo_super_hotkey_wmi_probe,
|
||||
.no_singleton = true,
|
||||
};
|
||||
|
||||
module_wmi_driver(lenovo_wmi_hotkey_utilities_driver);
|
||||
|
||||
MODULE_AUTHOR("Jackie Dong <dongeg1@lenovo.com>");
|
||||
MODULE_DESCRIPTION("Lenovo Super Hotkey Utility WMI extras driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -219,7 +219,7 @@ static int yt2_1380_fc_serdev_probe(struct serdev_device *serdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct serdev_device_driver yt2_1380_fc_serdev_driver = {
|
||||
static struct serdev_device_driver yt2_1380_fc_serdev_driver = {
|
||||
.probe = yt2_1380_fc_serdev_probe,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
|
|
|
|||
1425
drivers/platform/x86/samsung-galaxybook.c
Normal file
1425
drivers/platform/x86/samsung-galaxybook.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -262,16 +262,11 @@ static int tlmi_simple_call(const char *guid, const char *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Extract output string from WMI return buffer */
|
||||
static int tlmi_extract_output_string(const struct acpi_buffer *output,
|
||||
char **string)
|
||||
/* Extract output string from WMI return value */
|
||||
static int tlmi_extract_output_string(union acpi_object *obj, char **string)
|
||||
{
|
||||
const union acpi_object *obj;
|
||||
char *s;
|
||||
|
||||
obj = output->pointer;
|
||||
if (!obj)
|
||||
return -ENOMEM;
|
||||
if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer)
|
||||
return -EIO;
|
||||
|
||||
|
|
@ -349,20 +344,18 @@ static int tlmi_opcode_setting(char *setting, const char *value)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tlmi_setting(int item, char **value, const char *guid_string)
|
||||
static int tlmi_setting(struct wmi_device *wdev, int item, char **value)
|
||||
{
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
acpi_status status;
|
||||
union acpi_object *obj;
|
||||
int ret;
|
||||
|
||||
status = wmi_query_block(guid_string, item, &output);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
kfree(output.pointer);
|
||||
obj = wmidev_block_query(wdev, item);
|
||||
if (!obj)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = tlmi_extract_output_string(&output, value);
|
||||
kfree(output.pointer);
|
||||
ret = tlmi_extract_output_string(obj, value);
|
||||
kfree(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -370,19 +363,22 @@ static int tlmi_get_bios_selections(const char *item, char **value)
|
|||
{
|
||||
const struct acpi_buffer input = { strlen(item), (char *)item };
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *obj;
|
||||
acpi_status status;
|
||||
int ret;
|
||||
|
||||
status = wmi_evaluate_method(LENOVO_GET_BIOS_SELECTIONS_GUID,
|
||||
0, 0, &input, &output);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
kfree(output.pointer);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = tlmi_extract_output_string(&output, value);
|
||||
kfree(output.pointer);
|
||||
obj = output.pointer;
|
||||
if (!obj)
|
||||
return -ENODATA;
|
||||
|
||||
ret = tlmi_extract_output_string(obj, value);
|
||||
kfree(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -993,7 +989,7 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a
|
|||
char *item, *value;
|
||||
int ret;
|
||||
|
||||
ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID);
|
||||
ret = tlmi_setting(setting->wdev, setting->index, &item);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1586,7 +1582,7 @@ static struct tlmi_pwd_setting *tlmi_create_auth(const char *pwd_type,
|
|||
return new_pwd;
|
||||
}
|
||||
|
||||
static int tlmi_analyze(void)
|
||||
static int tlmi_analyze(struct wmi_device *wdev)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
|
|
@ -1623,7 +1619,7 @@ static int tlmi_analyze(void)
|
|||
char *item = NULL;
|
||||
|
||||
tlmi_priv.setting[i] = NULL;
|
||||
ret = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID);
|
||||
ret = tlmi_setting(wdev, i, &item);
|
||||
if (ret)
|
||||
break;
|
||||
if (!item)
|
||||
|
|
@ -1646,6 +1642,7 @@ static int tlmi_analyze(void)
|
|||
kfree(item);
|
||||
goto fail_clear_attr;
|
||||
}
|
||||
setting->wdev = wdev;
|
||||
setting->index = i;
|
||||
strscpy(setting->display_name, item);
|
||||
/* If BIOS selections supported, load those */
|
||||
|
|
@ -1664,7 +1661,7 @@ static int tlmi_analyze(void)
|
|||
*/
|
||||
char *optitem, *optstart, *optend;
|
||||
|
||||
if (!tlmi_setting(setting->index, &optitem, LENOVO_BIOS_SETTING_GUID)) {
|
||||
if (!tlmi_setting(setting->wdev, setting->index, &optitem)) {
|
||||
optstart = strstr(optitem, "[Optional:");
|
||||
if (optstart) {
|
||||
optstart += strlen("[Optional:");
|
||||
|
|
@ -1789,7 +1786,7 @@ static int tlmi_probe(struct wmi_device *wdev, const void *context)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = tlmi_analyze();
|
||||
ret = tlmi_analyze(wdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#define _THINK_LMI_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/wmi.h>
|
||||
|
||||
#define TLMI_SETTINGS_COUNT 256
|
||||
#define TLMI_SETTINGS_MAXLEN 512
|
||||
|
|
@ -87,6 +88,7 @@ struct tlmi_pwd_setting {
|
|||
/* Attribute setting details */
|
||||
struct tlmi_attr_setting {
|
||||
struct kobject kobj;
|
||||
struct wmi_device *wdev;
|
||||
int index;
|
||||
char display_name[TLMI_SETTINGS_MAXLEN];
|
||||
char *possible_values;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
|
|
@ -368,9 +367,6 @@ static struct {
|
|||
u32 beep_needs_two_args:1;
|
||||
u32 mixer_no_level_control:1;
|
||||
u32 battery_force_primary:1;
|
||||
u32 input_device_registered:1;
|
||||
u32 platform_drv_registered:1;
|
||||
u32 sensors_pdrv_registered:1;
|
||||
u32 hotkey_poll_active:1;
|
||||
u32 has_adaptive_kbd:1;
|
||||
u32 kbd_lang:1;
|
||||
|
|
@ -8513,7 +8509,7 @@ static void fan_watchdog_reset(void)
|
|||
if (fan_watchdog_maxinterval > 0 &&
|
||||
tpacpi_lifecycle != TPACPI_LIFE_EXITING)
|
||||
mod_delayed_work(tpacpi_wq, &fan_watchdog_task,
|
||||
msecs_to_jiffies(fan_watchdog_maxinterval * 1000));
|
||||
secs_to_jiffies(fan_watchdog_maxinterval));
|
||||
else
|
||||
cancel_delayed_work(&fan_watchdog_task);
|
||||
}
|
||||
|
|
@ -11817,36 +11813,18 @@ MODULE_PARM_DESC(profile_force, "Force profile mode. -1=off, 1=MMC, 2=PSC");
|
|||
|
||||
static void thinkpad_acpi_module_exit(void)
|
||||
{
|
||||
struct ibm_struct *ibm, *itmp;
|
||||
|
||||
tpacpi_lifecycle = TPACPI_LIFE_EXITING;
|
||||
|
||||
if (tpacpi_hwmon)
|
||||
hwmon_device_unregister(tpacpi_hwmon);
|
||||
if (tp_features.sensors_pdrv_registered)
|
||||
if (tpacpi_sensors_pdev) {
|
||||
platform_driver_unregister(&tpacpi_hwmon_pdriver);
|
||||
if (tp_features.platform_drv_registered)
|
||||
platform_driver_unregister(&tpacpi_pdriver);
|
||||
|
||||
list_for_each_entry_safe_reverse(ibm, itmp,
|
||||
&tpacpi_all_drivers,
|
||||
all_drivers) {
|
||||
ibm_exit(ibm);
|
||||
}
|
||||
|
||||
dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
|
||||
|
||||
if (tpacpi_inputdev) {
|
||||
if (tp_features.input_device_registered)
|
||||
input_unregister_device(tpacpi_inputdev);
|
||||
else
|
||||
input_free_device(tpacpi_inputdev);
|
||||
}
|
||||
|
||||
if (tpacpi_sensors_pdev)
|
||||
platform_device_unregister(tpacpi_sensors_pdev);
|
||||
if (tpacpi_pdev)
|
||||
}
|
||||
|
||||
if (tpacpi_pdev) {
|
||||
platform_driver_unregister(&tpacpi_pdriver);
|
||||
platform_device_unregister(tpacpi_pdev);
|
||||
}
|
||||
|
||||
if (proc_dir)
|
||||
remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir);
|
||||
if (tpacpi_wq)
|
||||
|
|
@ -11858,11 +11836,76 @@ static void thinkpad_acpi_module_exit(void)
|
|||
kfree(thinkpad_id.nummodel_str);
|
||||
}
|
||||
|
||||
static void tpacpi_subdrivers_release(void *data)
|
||||
{
|
||||
struct ibm_struct *ibm, *itmp;
|
||||
|
||||
list_for_each_entry_safe_reverse(ibm, itmp, &tpacpi_all_drivers, all_drivers)
|
||||
ibm_exit(ibm);
|
||||
|
||||
dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n");
|
||||
}
|
||||
|
||||
static int __init tpacpi_pdriver_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devm_mutex_init(&pdev->dev, &tpacpi_inputdev_send_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tpacpi_inputdev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!tpacpi_inputdev)
|
||||
return -ENOMEM;
|
||||
|
||||
tpacpi_inputdev->name = "ThinkPad Extra Buttons";
|
||||
tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0";
|
||||
tpacpi_inputdev->id.bustype = BUS_HOST;
|
||||
tpacpi_inputdev->id.vendor = thinkpad_id.vendor;
|
||||
tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
|
||||
tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
|
||||
tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
|
||||
|
||||
/* Init subdriver dependencies */
|
||||
tpacpi_detect_brightness_capabilities();
|
||||
|
||||
/* Init subdrivers */
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(ibms_init); i++) {
|
||||
ret = ibm_init(&ibms_init[i]);
|
||||
if (ret >= 0 && *ibms_init[i].param)
|
||||
ret = ibms_init[i].data->write(ibms_init[i].param);
|
||||
if (ret < 0) {
|
||||
tpacpi_subdrivers_release(NULL);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev, tpacpi_subdrivers_release, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = input_register_device(tpacpi_inputdev);
|
||||
if (ret < 0)
|
||||
pr_err("unable to register input device\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init tpacpi_hwmon_pdriver_probe(struct platform_device *pdev)
|
||||
{
|
||||
tpacpi_hwmon = devm_hwmon_device_register_with_groups(
|
||||
&tpacpi_sensors_pdev->dev, TPACPI_NAME, NULL, tpacpi_hwmon_groups);
|
||||
|
||||
if (IS_ERR(tpacpi_hwmon))
|
||||
pr_err("unable to register hwmon device\n");
|
||||
|
||||
return PTR_ERR_OR_ZERO(tpacpi_hwmon);
|
||||
}
|
||||
|
||||
static int __init thinkpad_acpi_module_init(void)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
int ret, i;
|
||||
int ret;
|
||||
acpi_object_type obj_type;
|
||||
|
||||
tpacpi_lifecycle = TPACPI_LIFE_INIT;
|
||||
|
|
@ -11922,93 +11965,29 @@ static int __init thinkpad_acpi_module_init(void)
|
|||
tp_features.quirks = dmi_id->driver_data;
|
||||
|
||||
/* Device initialization */
|
||||
tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, PLATFORM_DEVID_NONE,
|
||||
NULL, 0);
|
||||
tpacpi_pdev = platform_create_bundle(&tpacpi_pdriver, tpacpi_pdriver_probe,
|
||||
NULL, 0, NULL, 0);
|
||||
if (IS_ERR(tpacpi_pdev)) {
|
||||
ret = PTR_ERR(tpacpi_pdev);
|
||||
tpacpi_pdev = NULL;
|
||||
pr_err("unable to register platform device\n");
|
||||
pr_err("unable to register platform device/driver bundle\n");
|
||||
thinkpad_acpi_module_exit();
|
||||
return ret;
|
||||
}
|
||||
tpacpi_sensors_pdev = platform_device_register_simple(
|
||||
TPACPI_HWMON_DRVR_NAME,
|
||||
PLATFORM_DEVID_NONE, NULL, 0);
|
||||
|
||||
tpacpi_sensors_pdev = platform_create_bundle(&tpacpi_hwmon_pdriver,
|
||||
tpacpi_hwmon_pdriver_probe,
|
||||
NULL, 0, NULL, 0);
|
||||
if (IS_ERR(tpacpi_sensors_pdev)) {
|
||||
ret = PTR_ERR(tpacpi_sensors_pdev);
|
||||
tpacpi_sensors_pdev = NULL;
|
||||
pr_err("unable to register hwmon platform device\n");
|
||||
pr_err("unable to register hwmon platform device/driver bundle\n");
|
||||
thinkpad_acpi_module_exit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&tpacpi_inputdev_send_mutex);
|
||||
tpacpi_inputdev = input_allocate_device();
|
||||
if (!tpacpi_inputdev) {
|
||||
thinkpad_acpi_module_exit();
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
/* Prepare input device, but don't register */
|
||||
tpacpi_inputdev->name = "ThinkPad Extra Buttons";
|
||||
tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0";
|
||||
tpacpi_inputdev->id.bustype = BUS_HOST;
|
||||
tpacpi_inputdev->id.vendor = thinkpad_id.vendor;
|
||||
tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
|
||||
tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
|
||||
tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
|
||||
}
|
||||
|
||||
/* Init subdriver dependencies */
|
||||
tpacpi_detect_brightness_capabilities();
|
||||
|
||||
/* Init subdrivers */
|
||||
for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
|
||||
ret = ibm_init(&ibms_init[i]);
|
||||
if (ret >= 0 && *ibms_init[i].param)
|
||||
ret = ibms_init[i].data->write(ibms_init[i].param);
|
||||
if (ret < 0) {
|
||||
thinkpad_acpi_module_exit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
|
||||
|
||||
ret = platform_driver_register(&tpacpi_pdriver);
|
||||
if (ret) {
|
||||
pr_err("unable to register main platform driver\n");
|
||||
thinkpad_acpi_module_exit();
|
||||
return ret;
|
||||
}
|
||||
tp_features.platform_drv_registered = 1;
|
||||
|
||||
ret = platform_driver_register(&tpacpi_hwmon_pdriver);
|
||||
if (ret) {
|
||||
pr_err("unable to register hwmon platform driver\n");
|
||||
thinkpad_acpi_module_exit();
|
||||
return ret;
|
||||
}
|
||||
tp_features.sensors_pdrv_registered = 1;
|
||||
|
||||
tpacpi_hwmon = hwmon_device_register_with_groups(
|
||||
&tpacpi_sensors_pdev->dev, TPACPI_NAME, NULL, tpacpi_hwmon_groups);
|
||||
if (IS_ERR(tpacpi_hwmon)) {
|
||||
ret = PTR_ERR(tpacpi_hwmon);
|
||||
tpacpi_hwmon = NULL;
|
||||
pr_err("unable to register hwmon device\n");
|
||||
thinkpad_acpi_module_exit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = input_register_device(tpacpi_inputdev);
|
||||
if (ret < 0) {
|
||||
pr_err("unable to register input device\n");
|
||||
thinkpad_acpi_module_exit();
|
||||
return ret;
|
||||
} else {
|
||||
tp_features.input_device_registered = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,24 +123,6 @@ static const void *find_guid_context(struct wmi_block *wblock,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static acpi_status wmi_method_enable(struct wmi_block *wblock, bool enable)
|
||||
{
|
||||
struct guid_block *block;
|
||||
char method[5];
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
|
||||
block = &wblock->gblock;
|
||||
handle = wblock->acpi_device->handle;
|
||||
|
||||
snprintf(method, 5, "WE%02X", block->notify_id);
|
||||
status = acpi_execute_simple_method(handle, method, enable);
|
||||
if (status == AE_NOT_FOUND)
|
||||
return AE_OK;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define WMI_ACPI_METHOD_NAME_SIZE 5
|
||||
|
||||
static inline void get_acpi_method_name(const struct wmi_block *wblock,
|
||||
|
|
@ -184,6 +166,44 @@ static int wmidev_match_guid(struct device *dev, const void *data)
|
|||
|
||||
static const struct bus_type wmi_bus_type;
|
||||
|
||||
static const struct device_type wmi_type_event;
|
||||
|
||||
static const struct device_type wmi_type_method;
|
||||
|
||||
static int wmi_device_enable(struct wmi_device *wdev, bool enable)
|
||||
{
|
||||
struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
|
||||
char method[WMI_ACPI_METHOD_NAME_SIZE];
|
||||
acpi_handle handle;
|
||||
acpi_status status;
|
||||
|
||||
if (!(wblock->gblock.flags & ACPI_WMI_EXPENSIVE))
|
||||
return 0;
|
||||
|
||||
if (wblock->dev.dev.type == &wmi_type_method)
|
||||
return 0;
|
||||
|
||||
if (wblock->dev.dev.type == &wmi_type_event)
|
||||
snprintf(method, sizeof(method), "WE%02X", wblock->gblock.notify_id);
|
||||
else
|
||||
get_acpi_method_name(wblock, 'C', method);
|
||||
|
||||
/*
|
||||
* Not all WMI devices marked as expensive actually implement the
|
||||
* necessary ACPI method. Ignore this missing ACPI method to match
|
||||
* the behaviour of the Windows driver.
|
||||
*/
|
||||
status = acpi_get_handle(wblock->acpi_device->handle, method, &handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
|
||||
status = acpi_execute_simple_method(handle, NULL, enable);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct wmi_device *wmi_find_device_by_guid(const char *guid_string)
|
||||
{
|
||||
struct device *dev;
|
||||
|
|
@ -337,10 +357,8 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
|
|||
{
|
||||
struct guid_block *block;
|
||||
acpi_handle handle;
|
||||
acpi_status status, wc_status = AE_ERROR;
|
||||
struct acpi_object_list input;
|
||||
union acpi_object wq_params[1];
|
||||
char wc_method[WMI_ACPI_METHOD_NAME_SIZE];
|
||||
char method[WMI_ACPI_METHOD_NAME_SIZE];
|
||||
|
||||
if (!out)
|
||||
|
|
@ -364,40 +382,9 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
|
|||
if (instance == 0 && test_bit(WMI_READ_TAKES_NO_ARGS, &wblock->flags))
|
||||
input.count = 0;
|
||||
|
||||
/*
|
||||
* If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
|
||||
* enable collection.
|
||||
*/
|
||||
if (block->flags & ACPI_WMI_EXPENSIVE) {
|
||||
get_acpi_method_name(wblock, 'C', wc_method);
|
||||
|
||||
/*
|
||||
* Some GUIDs break the specification by declaring themselves
|
||||
* expensive, but have no corresponding WCxx method. So we
|
||||
* should not fail if this happens.
|
||||
*/
|
||||
wc_status = acpi_execute_simple_method(handle, wc_method, 1);
|
||||
}
|
||||
|
||||
get_acpi_method_name(wblock, 'Q', method);
|
||||
status = acpi_evaluate_object(handle, method, &input, out);
|
||||
|
||||
/*
|
||||
* If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
|
||||
* the WQxx method failed - we should disable collection anyway.
|
||||
*/
|
||||
if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
|
||||
/*
|
||||
* Ignore whether this WCxx call succeeds or not since
|
||||
* the previously executed WQxx method call might have
|
||||
* succeeded, and returning the failing status code
|
||||
* of this call would throw away the result of the WQxx
|
||||
* call, potentially leaking memory.
|
||||
*/
|
||||
acpi_execute_simple_method(handle, wc_method, 0);
|
||||
}
|
||||
|
||||
return status;
|
||||
return acpi_evaluate_object(handle, method, &input, out);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -421,9 +408,15 @@ acpi_status wmi_query_block(const char *guid_string, u8 instance,
|
|||
if (IS_ERR(wdev))
|
||||
return AE_ERROR;
|
||||
|
||||
if (wmi_device_enable(wdev, true) < 0)
|
||||
dev_warn(&wdev->dev, "Failed to enable device\n");
|
||||
|
||||
wblock = container_of(wdev, struct wmi_block, dev);
|
||||
status = __query_block(wblock, instance, out);
|
||||
|
||||
if (wmi_device_enable(wdev, false) < 0)
|
||||
dev_warn(&wdev->dev, "Failed to disable device\n");
|
||||
|
||||
wmi_device_put(wdev);
|
||||
|
||||
return status;
|
||||
|
|
@ -470,7 +463,14 @@ acpi_status wmi_set_block(const char *guid_string, u8 instance, const struct acp
|
|||
if (IS_ERR(wdev))
|
||||
return AE_ERROR;
|
||||
|
||||
if (wmi_device_enable(wdev, true) < 0)
|
||||
dev_warn(&wdev->dev, "Failed to enable device\n");
|
||||
|
||||
status = wmidev_block_set(wdev, instance, in);
|
||||
|
||||
if (wmi_device_enable(wdev, false) < 0)
|
||||
dev_warn(&wdev->dev, "Failed to disable device\n");
|
||||
|
||||
wmi_device_put(wdev);
|
||||
|
||||
return status;
|
||||
|
|
@ -551,7 +551,7 @@ acpi_status wmi_install_notify_handler(const char *guid,
|
|||
wblock->handler = handler;
|
||||
wblock->handler_data = data;
|
||||
|
||||
if (ACPI_FAILURE(wmi_method_enable(wblock, true)))
|
||||
if (wmi_device_enable(wdev, true) < 0)
|
||||
dev_warn(&wblock->dev.dev, "Failed to enable device\n");
|
||||
|
||||
status = AE_OK;
|
||||
|
|
@ -588,7 +588,7 @@ acpi_status wmi_remove_notify_handler(const char *guid)
|
|||
if (!wblock->handler) {
|
||||
status = AE_NULL_ENTRY;
|
||||
} else {
|
||||
if (ACPI_FAILURE(wmi_method_enable(wblock, false)))
|
||||
if (wmi_device_enable(wdev, false) < 0)
|
||||
dev_warn(&wblock->dev.dev, "Failed to disable device\n");
|
||||
|
||||
wblock->handler = NULL;
|
||||
|
|
@ -821,11 +821,19 @@ static int wmi_dev_match(struct device *dev, const struct device_driver *driver)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wmi_dev_disable(void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
if (wmi_device_enable(to_wmi_device(dev), false) < 0)
|
||||
dev_warn(dev, "Failed to disable device\n");
|
||||
}
|
||||
|
||||
static int wmi_dev_probe(struct device *dev)
|
||||
{
|
||||
struct wmi_block *wblock = dev_to_wblock(dev);
|
||||
struct wmi_driver *wdriver = to_wmi_driver(dev->driver);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
/* Some older WMI drivers will break if instantiated multiple times,
|
||||
* so they are blocked from probing WMI devices with a duplicated GUID.
|
||||
|
|
@ -844,18 +852,22 @@ static int wmi_dev_probe(struct device *dev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(wmi_method_enable(wblock, true)))
|
||||
if (wmi_device_enable(to_wmi_device(dev), true) < 0)
|
||||
dev_warn(dev, "failed to enable device -- probing anyway\n");
|
||||
|
||||
/*
|
||||
* We have to make sure that all devres-managed resources are released first because
|
||||
* some might still want to access the underlying WMI device.
|
||||
*/
|
||||
ret = devm_add_action_or_reset(dev, wmi_dev_disable, dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (wdriver->probe) {
|
||||
ret = wdriver->probe(to_wmi_device(dev),
|
||||
find_guid_context(wblock, wdriver));
|
||||
if (ret) {
|
||||
if (ACPI_FAILURE(wmi_method_enable(wblock, false)))
|
||||
dev_warn(dev, "Failed to disable device\n");
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
down_write(&wblock->notify_lock);
|
||||
|
|
@ -876,9 +888,6 @@ static void wmi_dev_remove(struct device *dev)
|
|||
|
||||
if (wdriver->remove)
|
||||
wdriver->remove(to_wmi_device(dev));
|
||||
|
||||
if (ACPI_FAILURE(wmi_method_enable(wblock, false)))
|
||||
dev_warn(dev, "failed to disable device\n");
|
||||
}
|
||||
|
||||
static void wmi_dev_shutdown(struct device *dev)
|
||||
|
|
@ -902,7 +911,11 @@ static void wmi_dev_shutdown(struct device *dev)
|
|||
if (wdriver->shutdown)
|
||||
wdriver->shutdown(to_wmi_device(dev));
|
||||
|
||||
if (ACPI_FAILURE(wmi_method_enable(wblock, false)))
|
||||
/*
|
||||
* We still need to disable the WMI device here since devres-managed resources
|
||||
* like wmi_dev_disable() will not be release during shutdown.
|
||||
*/
|
||||
if (wmi_device_enable(to_wmi_device(dev), false) < 0)
|
||||
dev_warn(dev, "Failed to disable device\n");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ config X86_ANDROID_TABLETS
|
|||
depends on ACPI && EFI && PCI
|
||||
select NEW_LEDS
|
||||
select LEDS_CLASS
|
||||
select POWER_SUPPLY
|
||||
help
|
||||
X86 tablets which ship with Android as (part of) the factory image
|
||||
typically have various problems with their DSDTs. The factory kernels
|
||||
|
|
|
|||
79
include/linux/platform_data/huawei-gaokun-ec.h
Normal file
79
include/linux/platform_data/huawei-gaokun-ec.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Huawei Matebook E Go Embedded Controller
|
||||
*
|
||||
* Copyright (C) 2024-2025 Pengyu Luo <mitltlatltl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __HUAWEI_GAOKUN_EC_H__
|
||||
#define __HUAWEI_GAOKUN_EC_H__
|
||||
|
||||
#define GAOKUN_UCSI_CCI_SIZE 4
|
||||
#define GAOKUN_UCSI_MSGI_SIZE 16
|
||||
#define GAOKUN_UCSI_READ_SIZE (GAOKUN_UCSI_CCI_SIZE + GAOKUN_UCSI_MSGI_SIZE)
|
||||
#define GAOKUN_UCSI_WRITE_SIZE 24 /* 8B CTRL, 16B MSGO */
|
||||
|
||||
#define GAOKUN_UCSI_NO_PORT_UPDATE (-1)
|
||||
|
||||
#define GAOKUN_SMART_CHARGE_DATA_SIZE 4 /* mode, delay, start, end */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
struct gaokun_ec;
|
||||
struct gaokun_ucsi_reg;
|
||||
struct notifier_block;
|
||||
|
||||
#define GAOKUN_MOD_NAME "huawei_gaokun_ec"
|
||||
#define GAOKUN_DEV_PSY "psy"
|
||||
#define GAOKUN_DEV_UCSI "ucsi"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Common API */
|
||||
|
||||
int gaokun_ec_register_notify(struct gaokun_ec *ec,
|
||||
struct notifier_block *nb);
|
||||
void gaokun_ec_unregister_notify(struct gaokun_ec *ec,
|
||||
struct notifier_block *nb);
|
||||
|
||||
int gaokun_ec_read(struct gaokun_ec *ec, const u8 *req,
|
||||
size_t resp_len, u8 *resp);
|
||||
int gaokun_ec_write(struct gaokun_ec *ec, const u8 *req);
|
||||
int gaokun_ec_read_byte(struct gaokun_ec *ec, const u8 *req, u8 *byte);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* API for PSY */
|
||||
|
||||
int gaokun_ec_psy_multi_read(struct gaokun_ec *ec, u8 reg,
|
||||
size_t resp_len, u8 *resp);
|
||||
|
||||
static inline int gaokun_ec_psy_read_byte(struct gaokun_ec *ec,
|
||||
u8 reg, u8 *byte)
|
||||
{
|
||||
return gaokun_ec_psy_multi_read(ec, reg, sizeof(*byte), byte);
|
||||
}
|
||||
|
||||
static inline int gaokun_ec_psy_read_word(struct gaokun_ec *ec,
|
||||
u8 reg, u16 *word)
|
||||
{
|
||||
return gaokun_ec_psy_multi_read(ec, reg, sizeof(*word), (u8 *)word);
|
||||
}
|
||||
|
||||
int gaokun_ec_psy_get_smart_charge(struct gaokun_ec *ec,
|
||||
u8 resp[GAOKUN_SMART_CHARGE_DATA_SIZE]);
|
||||
int gaokun_ec_psy_set_smart_charge(struct gaokun_ec *ec,
|
||||
const u8 req[GAOKUN_SMART_CHARGE_DATA_SIZE]);
|
||||
|
||||
int gaokun_ec_psy_get_smart_charge_enable(struct gaokun_ec *ec, bool *on);
|
||||
int gaokun_ec_psy_set_smart_charge_enable(struct gaokun_ec *ec, bool on);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* API for UCSI */
|
||||
|
||||
int gaokun_ec_ucsi_read(struct gaokun_ec *ec, u8 resp[GAOKUN_UCSI_READ_SIZE]);
|
||||
int gaokun_ec_ucsi_write(struct gaokun_ec *ec,
|
||||
const u8 req[GAOKUN_UCSI_WRITE_SIZE]);
|
||||
|
||||
int gaokun_ec_ucsi_get_reg(struct gaokun_ec *ec, struct gaokun_ucsi_reg *ureg);
|
||||
int gaokun_ec_ucsi_pan_ack(struct gaokun_ec *ec, int port_id);
|
||||
|
||||
#endif /* __HUAWEI_GAOKUN_EC_H__ */
|
||||
|
|
@ -13,7 +13,7 @@ endif
|
|||
# Do not use make's built-in rules
|
||||
# (this improves performance and avoids hard-to-debug behaviour);
|
||||
MAKEFLAGS += -r
|
||||
override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include -I/usr/include/libnl3
|
||||
override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include -I$(shell $(CC) -print-sysroot)/usr/include/libnl3
|
||||
override LDFLAGS += -lnl-genl-3 -lnl-3
|
||||
|
||||
ALL_TARGETS := intel-speed-select
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ struct process_cmd_struct {
|
|||
int arg;
|
||||
};
|
||||
|
||||
static const char *version_str = "v1.21";
|
||||
static const char *version_str = "v1.22";
|
||||
|
||||
static const int supported_api_ver = 3;
|
||||
static struct isst_if_platform_info isst_platform_info;
|
||||
|
|
@ -46,8 +46,9 @@ static int force_online_offline;
|
|||
static int auto_mode;
|
||||
static int fact_enable_fail;
|
||||
static int cgroupv2;
|
||||
static int max_pkg_id;
|
||||
static int max_die_id;
|
||||
static int max_punit_id;
|
||||
static int max_die_id_package_0;
|
||||
|
||||
/* clos related */
|
||||
static int current_clos = -1;
|
||||
|
|
@ -557,6 +558,8 @@ void for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void
|
|||
if (id.pkg < 0 || id.die < 0 || id.punit < 0)
|
||||
continue;
|
||||
|
||||
id.die = id.die % (max_die_id_package_0 + 1);
|
||||
|
||||
valid_mask[id.pkg][id.die] = 1;
|
||||
|
||||
if (cpus[id.pkg][id.die][id.punit] == -1)
|
||||
|
|
@ -564,11 +567,11 @@ void for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void
|
|||
}
|
||||
|
||||
for (i = 0; i < MAX_PACKAGE_COUNT; i++) {
|
||||
if (max_die_id == max_punit_id) {
|
||||
if (max_die_id > max_pkg_id) {
|
||||
for (k = 0; k < MAX_PUNIT_PER_DIE && k < MAX_DIE_PER_PACKAGE; k++) {
|
||||
id.cpu = cpus[i][k][k];
|
||||
id.pkg = i;
|
||||
id.die = k;
|
||||
id.die = get_physical_die_id(id.cpu);
|
||||
id.punit = k;
|
||||
if (isst_is_punit_valid(&id))
|
||||
callback(&id, arg1, arg2, arg3, arg4);
|
||||
|
|
@ -586,7 +589,10 @@ void for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void
|
|||
for (k = 0; k < MAX_PUNIT_PER_DIE; k++) {
|
||||
id.cpu = cpus[i][j][k];
|
||||
id.pkg = i;
|
||||
id.die = j;
|
||||
if (id.cpu >= 0)
|
||||
id.die = get_physical_die_id(id.cpu);
|
||||
else
|
||||
id.die = id.pkg;
|
||||
id.punit = k;
|
||||
if (isst_is_punit_valid(&id))
|
||||
callback(&id, arg1, arg2, arg3, arg4);
|
||||
|
|
@ -788,6 +794,8 @@ static void create_cpu_map(void)
|
|||
cpu_map[i].die_id = die_id;
|
||||
cpu_map[i].core_id = core_id;
|
||||
|
||||
if (max_pkg_id < pkg_id)
|
||||
max_pkg_id = pkg_id;
|
||||
|
||||
punit_id = 0;
|
||||
|
||||
|
|
@ -812,8 +820,8 @@ static void create_cpu_map(void)
|
|||
if (max_die_id < die_id)
|
||||
max_die_id = die_id;
|
||||
|
||||
if (max_punit_id < cpu_map[i].punit_id)
|
||||
max_punit_id = cpu_map[i].punit_id;
|
||||
if (!pkg_id && max_die_id_package_0 < die_id)
|
||||
max_die_id_package_0 = die_id;
|
||||
|
||||
debug_printf(
|
||||
"map logical_cpu:%d core: %d die:%d pkg:%d punit:%d punit_cpu:%d punit_core:%d\n",
|
||||
|
|
|
|||
|
|
@ -173,7 +173,11 @@ static int print_package_info(struct isst_id *id, FILE *outf)
|
|||
|
||||
if (out_format_is_json()) {
|
||||
if (api_version() > 1) {
|
||||
if (id->cpu < 0)
|
||||
if (id->die < 0 && id->cpu < 0)
|
||||
snprintf(header, sizeof(header),
|
||||
"package-%d:die-IO:powerdomain-%d:cpu-None",
|
||||
id->pkg, id->punit);
|
||||
else if (id->cpu < 0)
|
||||
snprintf(header, sizeof(header),
|
||||
"package-%d:die-%d:powerdomain-%d:cpu-None",
|
||||
id->pkg, id->die, id->punit);
|
||||
|
|
@ -190,7 +194,10 @@ static int print_package_info(struct isst_id *id, FILE *outf)
|
|||
}
|
||||
snprintf(header, sizeof(header), "package-%d", id->pkg);
|
||||
format_and_print(outf, level++, header, NULL);
|
||||
snprintf(header, sizeof(header), "die-%d", id->die);
|
||||
if (id->die < 0)
|
||||
snprintf(header, sizeof(header), "die-IO");
|
||||
else
|
||||
snprintf(header, sizeof(header), "die-%d", id->die);
|
||||
format_and_print(outf, level++, header, NULL);
|
||||
if (api_version() > 1) {
|
||||
snprintf(header, sizeof(header), "powerdomain-%d", id->punit);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user