platform-drivers-x86 for v5.15-1

Highlights:
  - Move all the Intel drivers into their own subdir(s) (mostly Kate's work)
  - New meraki-mx100 platform driver
  - Asus WMI driver enhancements, including
    /sys/firmware/acpi/platform_profile support
  - New BIOS SAR driver for Intel M.2 WWAM modems
  - Alder Lake support for the Intel PMC driver
  - A whole bunch of cleanups + fixes all over the place
 
 The following is an automated git shortlog grouped by driver:
 
 BIOS SAR driver for Intel M.2 Modem:
  - BIOS SAR driver for Intel M.2 Modem
 
 ISST:
  -  use semi-colons instead of commas
  -  Fix optimization with use of numa
 
 Replace deprecated CPU-hotplug functions.:
  - Replace deprecated CPU-hotplug functions.
 
 Update Mario Limonciello's email address in the docs:
  - Update Mario Limonciello's email address in the docs
 
 acer-wmi:
  -  Add Turbo Mode support for Acer PH315-53
 
 add meraki-mx100 platform driver:
  - add meraki-mx100 platform driver
 
 asus-nb-wmi:
  -  Add tablet_mode_sw=lid-flip quirk for the TP200s
  -  Allow configuring SW_TABLET_MODE method with a module option
 
 asus-wmi:
  -  Fix "unsigned 'retval' is never less than zero" smatch warning
  -  Delete impossible condition
  -  Add support for platform_profile
  -  Add egpu enable method
  -  Add dgpu disable method
  -  Add panel overdrive functionality
 
 dell-smbios:
  -  Remove unused dmi_system_id table
 
 dell-smbios-wmi:
  -  Add missing kfree in error-exit from run_smbios_call
  -  Avoid false-positive memcpy() warning
 
 dell-smo8800:
  -  Convert to be a platform driver
 
 dual_accel_detect:
  -  Use the new i2c_acpi_client_count() helper
 
 gigabyte-wmi:
  -  add support for B450M S2H V2
  -  add support for X570 GAMING X
 
 hp_accel:
  -  Convert to be a platform driver
  -  Remove _INI method call
 
 i2c:
  -  acpi: Add an i2c_acpi_client_count() helper function
 
 i2c-multi-instantiate:
  -  Use the new i2c_acpi_client_count() helper
 
 ideapad-laptop:
  -  Fix Legion 5 Fn lock LED
 
 intel-hid:
  -  Move to intel sub-directory
 
 intel-rst:
  -  Move to intel sub-directory
 
 intel-smartconnect:
  -  Move to intel sub-directory
 
 intel-uncore-frequency:
  -  Move to intel sub-directory
 
 intel-vbtn:
  -  Move to intel sub-directory
 
 intel-wmi-sbl-fw-update:
  -  Move to intel sub-directory
 
 intel-wmi-thunderbolt:
  -  Move to intel sub-directory
 
 intel_atomisp2:
  -  Move to intel sub-directory
 
 intel_bxtwc_tmu:
  -  Move to intel sub-directory
 
 intel_cht_int33fe:
  -  Use the new i2c_acpi_client_count() helper
 
 intel_chtdc_ti_pwrbtn:
  -  Move to intel sub-directory
 
 intel_int0002_vgpio:
  -  Move to intel sub-directory
 
 intel_mrfld_pwrbtn:
  -  Move to intel sub-directory
 
 intel_oaktrail:
  -  Move to intel sub-directory
 
 intel_pmc_core:
  -  Move to intel sub-directory
  -  Prevent possibile overflow
 
 intel_pmt_telemetry:
  -  Ignore zero sized entries
 
 intel_punit_ipc:
  -  Move to intel sub-directory
 
 intel_scu_ipc:
  -  Fix doc of intel_scu_ipc_dev_command_with_size()
 
 intel_speed_select_if:
  -  Move to intel sub-directory
 
 intel_telemetry:
  -  Move to intel sub-directory
 
 intel_turbo_max_3:
  -  Move to intel sub-directory
 
 lg-laptop:
  -  Use correct event for keyboard backlight FN-key
  -  Use correct event for touchpad toggle FN-key
  -  Support for battery charge limit on newer models
 
 platform/mellanox:
  -  mlxbf-pmc: fix kernel-doc notation
 
 platform/surface:
  -  aggregator: Use y instead of objs in Makefile
  -  surface3_power: Use i2c_acpi_get_i2c_resource() helper
 
 platform/x86/intel:
  -  pmc/core: Add GBE Package C10 fix for Alder Lake PCH
  -  pmc/core: Add Alder Lake low power mode support for pmc core
  -  pmc/core: Add Latency Tolerance Reporting (LTR) support to Alder Lake
  -  pmc/core: Add Alderlake support to pmc core driver
  -  int3472: Use y instead of objs in Makefile
  -  pmt: Use y instead of objs in Makefile
  -  int33fe: Use y instead of objs in Makefile
  -  Move Intel PMT drivers to new subfolder
 
 thermal/drivers/intel:
  -  Move intel_menlow to thermal drivers
 
 think-lmi:
  -  add debug_cmd
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmEw1KAUHGhkZWdvZWRl
 QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9wk7Qf/dsaaDgx7aC6DfKzdcMgfeLIdTaGm
 a6svNXM2t/JFdvhjYzxA+4QlQgco7zkN06iRlWbObEonSUsHlGlwEOHX60VgcopO
 qJaqnznmfdXUocFTnA+5acJXabNaw7xkKHS0K61UWgk+mm6aMuygpKxULnNTa4X+
 p3HoU6uXFckpoA/Jstzo5UfegNYhg11bflNd7XN4F3rMCbbNHAsWlf4oVr2YsEHa
 wECW+1e8wZl4BInUzoXQhilRoybJWXWJ8sLsvQfDXLs9aNoLdDqu9p0MuXEW5QqE
 wNt26SNNAP2L49BD6kaJszV5Ry/jNSEtVkWwkrzHbGTZoOEyMYas8pm6Uw==
 =iK1W
 -----END PGP SIGNATURE-----

Merge tag 'platform-drivers-x86-v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver updates from Hans de Goede:
 "Highlights:

   - Move all the Intel drivers into their own subdir(s) (mostly Kate's
     work)

   - New meraki-mx100 platform driver

   - Asus WMI driver enhancements, including support for
     /sys/firmware/acpi/platform_profile

   - New BIOS SAR driver for Intel M.2 WWAM modems

   - Alder Lake support for the Intel PMC driver

   - A whole bunch of cleanups + fixes all over the place"

* tag 'platform-drivers-x86-v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (65 commits)
  platform/x86: dell-smbios-wmi: Add missing kfree in error-exit from run_smbios_call
  platform/x86: dell-smbios-wmi: Avoid false-positive memcpy() warning
  platform/x86: ISST: use semi-colons instead of commas
  platform/x86: asus-wmi: Fix "unsigned 'retval' is never less than zero" smatch warning
  platform/x86: asus-wmi: Delete impossible condition
  platform/x86: hp_accel: Convert to be a platform driver
  platform/x86: hp_accel: Remove _INI method call
  platform/mellanox: mlxbf-pmc: fix kernel-doc notation
  platform/x86/intel: pmc/core: Add GBE Package C10 fix for Alder Lake PCH
  platform/x86/intel: pmc/core: Add Alder Lake low power mode support for pmc core
  platform/x86/intel: pmc/core: Add Latency Tolerance Reporting (LTR) support to Alder Lake
  platform/x86/intel: pmc/core: Add Alderlake support to pmc core driver
  platform/x86: intel-wmi-thunderbolt: Move to intel sub-directory
  platform/x86: intel-wmi-sbl-fw-update: Move to intel sub-directory
  platform/x86: intel-vbtn: Move to intel sub-directory
  platform/x86: intel_oaktrail: Move to intel sub-directory
  platform/x86: intel_int0002_vgpio: Move to intel sub-directory
  platform/x86: intel-hid: Move to intel sub-directory
  platform/x86: intel_atomisp2: Move to intel sub-directory
  platform/x86: intel_speed_select_if: Move to intel sub-directory
  ...
This commit is contained in:
Linus Torvalds 2021-09-02 13:49:39 -07:00
commit 7ba88a2a09
89 changed files with 2431 additions and 638 deletions

View File

@ -1,7 +1,7 @@
What: /dev/wmi/dell-smbios
Date: November 2017
KernelVersion: 4.15
Contact: "Mario Limonciello" <mario.limonciello@dell.com>
Contact: Dell.Client.Kernel@dell.com
Description:
Perform SMBIOS calls on supported Dell machines.
through the Dell ACPI-WMI interface.

View File

@ -232,7 +232,7 @@ Description: When new NVM image is written to the non-active NVM
What: /sys/bus/thunderbolt/devices/.../nvm_authenticate_on_disconnect
Date: Oct 2020
KernelVersion: v5.9
Contact: Mario Limonciello <mario.limonciello@dell.com>
Contact: Mario Limonciello <mario.limonciello@outlook.com>
Description: For supported devices, automatically authenticate the new Thunderbolt
image when the device is disconnected from the host system.

View File

@ -2,8 +2,8 @@ What: /sys/class/firmware-attributes/*/attributes/*/
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
Dell.Client.Kernel@dell.com
Description:
A sysfs interface for systems management software to enable
configuration capability on supported systems. This directory
@ -130,8 +130,8 @@ What: /sys/class/firmware-attributes/*/authentication/
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
Dell.Client.Kernel@dell.com
Description:
Devices support various authentication mechanisms which can be exposed
as a separate configuration object.
@ -220,8 +220,8 @@ What: /sys/class/firmware-attributes/*/attributes/pending_reboot
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
Dell.Client.Kernel@dell.com
Description:
A read-only attribute reads 1 if a reboot is necessary to apply
pending BIOS attribute changes. Also, an uevent_KOBJ_CHANGE is
@ -249,8 +249,8 @@ What: /sys/class/firmware-attributes/*/attributes/reset_bios
Date: February 2021
KernelVersion: 5.11
Contact: Divya Bharathi <Divya.Bharathi@Dell.com>,
Mario Limonciello <mario.limonciello@dell.com>,
Prasanth KSR <prasanth.ksr@dell.com>
Dell.Client.Kernel@dell.com
Description:
This attribute can be used to reset the BIOS Configuration.
Specifically, it tells which type of reset BIOS configuration is being
@ -272,3 +272,14 @@ Description:
Note that any changes to this attribute requires a reboot
for changes to take effect.
What: /sys/class/firmware-attributes/*/attributes/debug_cmd
Date: July 2021
KernelVersion: 5.14
Contact: Mark Pearson <markpearson@lenovo.com>
Description:
This write only attribute can be used to send debug commands to the BIOS.
This should only be used when recommended by the BIOS vendor. Vendors may
use it to enable extra debug attributes or BIOS features for testing purposes.
Note that any changes to this attribute requires a reboot for changes to take effect.

View File

@ -0,0 +1,54 @@
What: /sys/bus/platform/devices/INTC1092:00/intc_reg
Date: August 2021
KernelVersion: 5.15
Contact: Shravan S <s.shravan@intel.com>,
An Sudhakar <sudhakar.an@intel.com>
Description:
Specific Absorption Rate (SAR) regulatory mode is typically
derived based on information like mcc (Mobile Country Code) and
mnc (Mobile Network Code) that is available for the currently
attached LTE network. A userspace application is required to set
the current SAR regulatory mode on the Dynamic SAR driver using
this sysfs node. Such an application can also read back using
this sysfs node, the currently configured regulatory mode value
from the Dynamic SAR driver.
Acceptable regulatory modes are:
== ====
0 FCC
1 CE
2 ISED
== ====
- The regulatory mode value has one of the above values.
- The default regulatory mode used in the driver is 0.
What: /sys/bus/platform/devices/INTC1092:00/intc_data
Date: August 2021
KernelVersion: 5.15
Contact: Shravan S <s.shravan@intel.com>,
An Sudhakar <sudhakar.an@intel.com>
Description:
This sysfs entry is used to retrieve Dynamic SAR information
emitted/maintained by a BIOS that supports Dynamic SAR.
The retrieved information is in the order given below:
- device_mode
- bandtable_index
- antennatable_index
- sartable_index
The above information is sent as integer values separated
by a single space. This information can then be pushed to a
WWAN modem that uses this to control the transmit signal
level using the Band/Antenna/SAR table index information.
These parameters are derived/decided by aggregating
device-mode like laptop/tablet/clamshell etc. and the
proximity-sensor data available to the embedded controller on
given host. The regulatory mode configured on Dynamic SAR
driver also influences these values.
The userspace applications can poll for changes to this file
using POLLPRI event on file-descriptor (fd) obtained by opening
this sysfs entry. Application can then read this information from
the sysfs node and consume the given information.

View File

@ -1,7 +1,7 @@
What: /sys/devices/platform/<platform>/tokens/*
Date: November 2017
KernelVersion: 4.15
Contact: "Mario Limonciello" <mario.limonciello@dell.com>
Contact: Dell.Client.Kernel@dell.com
Description:
A read-only description of Dell platform tokens
available on the machine.

View File

@ -1,7 +1,7 @@
What: /sys/devices/platform/<platform>/force_power
Date: September 2017
KernelVersion: 4.15
Contact: "Mario Limonciello" <mario.limonciello@dell.com>
Contact: "Mario Limonciello" <mario.limonciello@outlook.com>
Description:
Modify the platform force power state, influencing
Thunderbolt controllers to turn on or off when no

View File

@ -295,7 +295,7 @@ Description:
What: /sys/power/resume_offset
Date: April 2018
Contact: Mario Limonciello <mario.limonciello@dell.com>
Contact: Mario Limonciello <mario.limonciello@outlook.com>
Description:
This file is used for telling the kernel an offset into a disk
to use when hibernating the system such as with a swap file.

View File

@ -13,10 +13,8 @@ Hotkeys
The following FN keys are ignored by the kernel without this driver:
- FN-F1 (LG control panel) - Generates F15
- FN-F5 (Touchpad toggle) - Generates F13
- FN-F5 (Touchpad toggle) - Generates F21
- FN-F6 (Airplane mode) - Generates RFKILL
- FN-F8 (Keyboard backlight) - Generates F16.
This key also changes keyboard backlight mode.
- FN-F9 (Reader mode) - Generates F14
The rest of the FN keys work without a need for a special driver.

View File

@ -9269,13 +9269,20 @@ INTEL ATOMISP2 DUMMY / POWER-MANAGEMENT DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel_atomisp2_pm.c
F: drivers/platform/x86/intel/atomisp2/pm.c
INTEL ATOMISP2 LED DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel_atomisp2_led.c
F: drivers/platform/x86/intel/atomisp2/led.c
INTEL BIOS SAR INT1092 DRIVER
M: Shravan S <s.shravan@intel.com>
M: Intel Corporation <linuxwwan@intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel/int1092/
INTEL BROXTON PMC DRIVER
M: Mika Westerberg <mika.westerberg@linux.intel.com>
@ -9371,7 +9378,7 @@ INTEL HID EVENT DRIVER
M: Alex Hung <alex.hung@canonical.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel-hid.c
F: drivers/platform/x86/intel/hid.c
INTEL I/OAT DMA DRIVER
M: Dave Jiang <dave.jiang@intel.com>
@ -9515,17 +9522,17 @@ F: include/linux/mfd/intel-m10-bmc.h
INTEL MENLOW THERMAL DRIVER
M: Sujith Thomas <sujith.thomas@intel.com>
L: platform-driver-x86@vger.kernel.org
L: linux-pm@vger.kernel.org
S: Supported
W: https://01.org/linux-acpi
F: drivers/platform/x86/intel_menlow.c
F: drivers/thermal/intel/intel_menlow.c
INTEL P-Unit IPC DRIVER
M: Zha Qipeng <qipeng.zha@intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: arch/x86/include/asm/intel_punit_ipc.h
F: drivers/platform/x86/intel_punit_ipc.c
F: drivers/platform/x86/intel/punit_ipc.c
INTEL PMC CORE DRIVER
M: Rajneesh Bhardwaj <irenic.rajneesh@gmail.com>
@ -9533,7 +9540,7 @@ M: David E Box <david.e.box@intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-platform-intel-pmc
F: drivers/platform/x86/intel_pmc_core*
F: drivers/platform/x86/intel/pmc/
INTEL PMIC GPIO DRIVERS
M: Andy Shevchenko <andy@kernel.org>
@ -9551,7 +9558,7 @@ INTEL PMT DRIVER
M: "David E. Box" <david.e.box@linux.intel.com>
S: Maintained
F: drivers/mfd/intel_pmt.c
F: drivers/platform/x86/intel_pmt_*
F: drivers/platform/x86/intel/pmt/
INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
M: Stanislav Yakovlev <stas.yakovlev@gmail.com>
@ -9588,7 +9595,7 @@ INTEL SPEED SELECT TECHNOLOGY
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel_speed_select_if/
F: drivers/platform/x86/intel/speed_select_if/
F: include/uapi/linux/isst_if.h
F: tools/power/x86/intel-speed-select/
@ -9609,19 +9616,19 @@ M: "David E. Box" <david.e.box@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: arch/x86/include/asm/intel_telemetry.h
F: drivers/platform/x86/intel_telemetry*
F: drivers/platform/x86/intel/telemetry/
INTEL UNCORE FREQUENCY CONTROL
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel-uncore-frequency.c
F: drivers/platform/x86/intel/uncore-frequency.c
INTEL VIRTUAL BUTTON DRIVER
M: AceLan Kao <acelan.kao@canonical.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel-vbtn.c
F: drivers/platform/x86/intel/vbtn.c
INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy)
M: Stanislaw Gruszka <stf_xl@wp.pl>
@ -9642,12 +9649,12 @@ M: Jithu Joseph <jithu.joseph@intel.com>
R: Maurice Ma <maurice.ma@intel.com>
S: Maintained
W: https://slimbootloader.github.io/security/firmware-update.html
F: drivers/platform/x86/intel-wmi-sbl-fw-update.c
F: drivers/platform/x86/intel/wmi/sbl-fw-update.c
INTEL WMI THUNDERBOLT FORCE POWER DRIVER
L: Dell.Client.Kernel@dell.com
S: Maintained
F: drivers/platform/x86/intel-wmi-thunderbolt.c
F: drivers/platform/x86/intel/wmi/thunderbolt.c
INTEL WWAN IOSM DRIVER
M: M Chetan Kumar <m.chetan.kumar@intel.com>

View File

@ -69,6 +69,38 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
}
EXPORT_SYMBOL_GPL(i2c_acpi_get_i2c_resource);
static int i2c_acpi_resource_count(struct acpi_resource *ares, void *data)
{
struct acpi_resource_i2c_serialbus *sb;
int *count = data;
if (i2c_acpi_get_i2c_resource(ares, &sb))
*count = *count + 1;
return 1;
}
/**
* i2c_acpi_client_count - Count the number of I2cSerialBus resources
* @adev: ACPI device
*
* Returns the number of I2cSerialBus resources in the ACPI-device's
* resource-list; or a negative error code.
*/
int i2c_acpi_client_count(struct acpi_device *adev)
{
int ret, count = 0;
LIST_HEAD(r);
ret = acpi_dev_get_resources(adev, &r, i2c_acpi_resource_count, &count);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&r);
return count;
}
EXPORT_SYMBOL_GPL(i2c_acpi_client_count);
static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
{
struct i2c_acpi_lookup *lookup = data;

View File

@ -271,7 +271,6 @@ struct lis3lv02d {
int regs_size;
u8 *reg_cache;
bool regs_stored;
bool init_required;
u8 odr_mask; /* ODR bit mask */
u8 whoami; /* indicates measurement precision */
s16 (*read_data) (struct lis3lv02d *lis3, int reg);

View File

@ -79,7 +79,8 @@
#define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0)
/**
* Structure to hold attribute and block info for each sysfs entry
* struct mlxbf_pmc_attribute - Structure to hold attribute and block info
* for each sysfs entry
* @dev_attr: Device attribute struct
* @index: index to identify counter number within a block
* @nr: block number to which the sysfs belongs
@ -91,7 +92,7 @@ struct mlxbf_pmc_attribute {
};
/**
* Structure to hold info for each HW block
* struct mlxbf_pmc_block_info - Structure to hold info for each HW block
*
* @mmio_base: The VA at which the PMC block is mapped
* @blk_size: Size of each mapped region
@ -102,7 +103,7 @@ struct mlxbf_pmc_attribute {
* @attr_event_list: Attributes for "event_list" sysfs files
* @attr_enable: Attributes for "enable" sysfs files
* @block_attr: All attributes needed for the block
* @blcok_attr_grp: Attribute group for the block
* @block_attr_grp: Attribute group for the block
*/
struct mlxbf_pmc_block_info {
void __iomem *mmio_base;
@ -118,7 +119,7 @@ struct mlxbf_pmc_block_info {
};
/**
* Structure to hold PMC context info
* struct mlxbf_pmc_context - Structure to hold PMC context info
*
* @pdev: The kernel structure representing the device
* @total_blocks: Total number of blocks
@ -127,7 +128,7 @@ struct mlxbf_pmc_block_info {
* @block_name: Block name
* @block: Block info
* @groups: Attribute groups from each block
* @sv_sreg_support: Whether SMCs are used to access performance registers
* @svc_sreg_support: Whether SMCs are used to access performance registers
* @sreg_tbl_perf: Secure register access table number
* @event_set: Event set to use
*/
@ -145,7 +146,7 @@ struct mlxbf_pmc_context {
};
/**
* Structure to hold supported events for each block
* struct mlxbf_pmc_events - Structure to hold supported events for each block
* @evt_num: Event number used to program counters
* @evt_name: Name of the event
*/

View File

@ -6,12 +6,9 @@ CFLAGS_core.o = -I$(src)
obj-$(CONFIG_SURFACE_AGGREGATOR) += surface_aggregator.o
surface_aggregator-objs := core.o
surface_aggregator-objs += ssh_parser.o
surface_aggregator-objs += ssh_packet_layer.o
surface_aggregator-objs += ssh_request_layer.o
surface_aggregator-objs += controller.o
ifeq ($(CONFIG_SURFACE_AGGREGATOR_BUS),y)
surface_aggregator-objs += bus.o
endif
surface_aggregator-y := core.o
surface_aggregator-y += ssh_parser.o
surface_aggregator-y += ssh_packet_layer.o
surface_aggregator-y += ssh_request_layer.o
surface_aggregator-$(CONFIG_SURFACE_AGGREGATOR_BUS) += bus.o
surface_aggregator-y += controller.o

View File

@ -384,13 +384,7 @@ mshw0011_space_handler(u32 function, acpi_physical_address command,
if (ACPI_FAILURE(ret))
return ret;
if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
ret = AE_BAD_PARAMETER;
goto err;
}
sb = &ares->data.i2c_serial_bus;
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) {
ret = AE_BAD_PARAMETER;
goto err;
}

View File

@ -77,28 +77,6 @@ config UV_SYSFS
To compile this driver as a module, choose M here: the module will
be called uv_sysfs.
config INTEL_WMI_SBL_FW_UPDATE
tristate "Intel WMI Slim Bootloader firmware update signaling driver"
depends on ACPI_WMI
help
Say Y here if you want to be able to use the WMI interface to signal
Slim Bootloader to trigger update on next reboot.
To compile this driver as a module, choose M here: the module will
be called intel-wmi-sbl-fw-update.
config INTEL_WMI_THUNDERBOLT
tristate "Intel WMI thunderbolt force power driver"
depends on ACPI_WMI
help
Say Y here if you want to be able to use the WMI interface on select
systems to force the power control of Intel Thunderbolt controllers.
This is useful for updating the firmware when devices are not plugged
into the controller.
To compile this driver as a module, choose M here: the module will
be called intel-wmi-thunderbolt.
config MXM_WMI
tristate "WMI support for MXM Laptop Graphics"
depends on ACPI_WMI
@ -281,6 +259,7 @@ config ASUS_WMI
select INPUT_SPARSEKMAP
select LEDS_CLASS
select NEW_LEDS
select ACPI_PLATFORM_PROFILE
help
Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new
Asus Notebooks).
@ -302,6 +281,19 @@ config ASUS_NB_WMI
If you have an ACPI-WMI compatible Asus Notebook, say Y or M
here.
config MERAKI_MX100
tristate "Cisco Meraki MX100 Platform Driver"
depends on GPIOLIB
depends on GPIO_ICH
depends on LEDS_CLASS
select LEDS_GPIO
help
This driver provides support for the front button and LEDs on
the Cisco Meraki MX100 (Tinkerbell) 1U appliance.
To compile this driver as a module, choose M here: the module
will be called meraki-mx100.
config EEEPC_LAPTOP
tristate "Eee PC Hotkey Driver"
depends on ACPI
@ -654,105 +646,6 @@ config THINKPAD_LMI
source "drivers/platform/x86/intel/Kconfig"
config INTEL_ATOMISP2_LED
tristate "Intel AtomISP2 camera LED driver"
depends on GPIOLIB && LEDS_GPIO
help
Many Bay Trail and Cherry Trail devices come with a camera attached
to Intel's Image Signal Processor. Linux currently does not have a
driver for these, so they do not work as a camera. Some of these
camera's have a LED which is controlled through a GPIO.
Some of these devices have a firmware issue where the LED gets turned
on at boot. This driver will turn the LED off at boot and also allows
controlling the LED (repurposing it) through the sysfs LED interface.
Which GPIO is attached to the LED is usually not described in the
ACPI tables, so this driver contains per-system info about the GPIO
inside the driver, this means that this driver only works on systems
the driver knows about.
To compile this driver as a module, choose M here: the module
will be called intel_atomisp2_led.
config INTEL_ATOMISP2_PM
tristate "Intel AtomISP2 dummy / power-management driver"
depends on PCI && IOSF_MBI && PM
depends on !INTEL_ATOMISP
help
Power-management driver for Intel's Image Signal Processor found on
Bay Trail and Cherry Trail devices. This dummy driver's sole purpose
is to turn the ISP off (put it in D3) to save power and to allow
entering of S0ix modes.
To compile this driver as a module, choose M here: the module
will be called intel_atomisp2_pm.
config INTEL_HID_EVENT
tristate "INTEL HID Event"
depends on ACPI
depends on INPUT
depends on I2C
select INPUT_SPARSEKMAP
help
This driver provides support for the Intel HID Event hotkey interface.
Some laptops require this driver for hotkey support.
To compile this driver as a module, choose M here: the module will
be called intel_hid.
config INTEL_INT0002_VGPIO
tristate "Intel ACPI INT0002 Virtual GPIO driver"
depends on GPIOLIB && ACPI && PM_SLEEP
select GPIOLIB_IRQCHIP
help
Some peripherals on Bay Trail and Cherry Trail platforms signal a
Power Management Event (PME) to the Power Management Controller (PMC)
to wakeup the system. When this happens software needs to explicitly
clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
IRQ storm on IRQ 9.
This is modelled in ACPI through the INT0002 ACPI device, which is
called a "Virtual GPIO controller" in ACPI because it defines the
event handler to call when the PME triggers through _AEI and _L02
methods as would be done for a real GPIO interrupt in ACPI.
To compile this driver as a module, choose M here: the module will
be called intel_int0002_vgpio.
config INTEL_MENLOW
tristate "Thermal Management driver for Intel menlow platform"
depends on ACPI_THERMAL
select THERMAL
help
ACPI thermal management enhancement driver on
Intel Menlow platform.
If unsure, say N.
config INTEL_OAKTRAIL
tristate "Intel Oaktrail Platform Extras"
depends on ACPI
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI
help
Intel Oaktrail platform need this driver to provide interfaces to
enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
here; it will only load on supported platforms.
config INTEL_VBTN
tristate "INTEL VIRTUAL BUTTON"
depends on ACPI
depends on INPUT
depends on I2C
select INPUT_SPARSEKMAP
help
This driver provides support for the Intel Virtual Button interface.
Some laptops require this driver for power button support.
To compile this driver as a module, choose M here: the module will
be called intel_vbtn.
config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on ACPI
@ -1106,150 +999,6 @@ config INTEL_IPS
functionality. If in doubt, say Y here; it will only load on
supported platforms.
config INTEL_RST
tristate "Intel Rapid Start Technology Driver"
depends on ACPI
help
This driver provides support for modifying parameters on systems
equipped with Intel's Rapid Start Technology. When put in an ACPI
sleep state, these devices will wake after either a configured
timeout or when the system battery reaches a critical state,
automatically copying memory contents to disk. On resume, the
firmware will copy the memory contents back to RAM and resume the OS
as usual.
config INTEL_SMARTCONNECT
tristate "Intel Smart Connect disabling driver"
depends on ACPI
help
Intel Smart Connect is a technology intended to permit devices to
update state by resuming for a short period of time at regular
intervals. If a user enables this functionality under Windows and
then reboots into Linux, the system may remain configured to resume
on suspend. In the absence of any userspace to support it, the system
will then remain awake until something triggers another suspend.
This driver checks to determine whether the device has Intel Smart
Connect enabled, and if so disables it.
source "drivers/platform/x86/intel_speed_select_if/Kconfig"
config INTEL_TURBO_MAX_3
bool "Intel Turbo Boost Max Technology 3.0 enumeration driver"
depends on X86_64 && SCHED_MC_PRIO
help
This driver reads maximum performance ratio of each CPU and set up
the scheduler priority metrics. In this way scheduler can prefer
CPU with higher performance to schedule tasks.
This driver is only required when the system is not using Hardware
P-States (HWP). In HWP mode, priority can be read from ACPI tables.
config INTEL_UNCORE_FREQ_CONTROL
tristate "Intel Uncore frequency control driver"
depends on X86_64
help
This driver allows control of uncore frequency limits on
supported server platforms.
Uncore frequency controls RING/LLC (last-level cache) clocks.
To compile this driver as a module, choose M here: the module
will be called intel-uncore-frequency.
config INTEL_BXTWC_PMIC_TMU
tristate "Intel BXT Whiskey Cove TMU Driver"
depends on REGMAP
depends on MFD_INTEL_PMC_BXT
depends on INTEL_SOC_PMIC_BXTWC
help
Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature.
This driver enables the alarm wakeup functionality in the TMU unit
of Whiskey Cove PMIC.
config INTEL_CHTDC_TI_PWRBTN
tristate "Intel Cherry Trail Dollar Cove TI power button driver"
depends on INTEL_SOC_PMIC_CHTDC_TI
depends on INPUT
help
This option adds a power button driver driver for Dollar Cove TI
PMIC on Intel Cherry Trail devices.
To compile this driver as a module, choose M here: the module
will be called intel_chtdc_ti_pwrbtn.
config INTEL_MRFLD_PWRBTN
tristate "Intel Merrifield Basin Cove power button driver"
depends on INTEL_SOC_PMIC_MRFLD
depends on INPUT
help
This option adds a power button driver for Basin Cove PMIC
on Intel Merrifield devices.
To compile this driver as a module, choose M here: the module
will be called intel_mrfld_pwrbtn.
config INTEL_PMC_CORE
tristate "Intel PMC Core driver"
depends on PCI
depends on ACPI
help
The Intel Platform Controller Hub for Intel Core SoCs provides access
to Power Management Controller registers via various interfaces. This
driver can utilize debugging capabilities and supported features as
exposed by the Power Management Controller. It also may perform some
tasks in the PMC in order to enable transition into the SLPS0 state.
It should be selected on all Intel platforms supported by the driver.
Supported features:
- SLP_S0_RESIDENCY counter
- PCH IP Power Gating status
- LTR Ignore / LTR Show
- MPHY/PLL gating status (Sunrisepoint PCH only)
- SLPS0 Debug registers (Cannonlake/Icelake PCH)
- Low Power Mode registers (Tigerlake and beyond)
- PMC quirks as needed to enable SLPS0/S0ix
config INTEL_PMT_CLASS
tristate
help
The Intel Platform Monitoring Technology (PMT) class driver provides
the basic sysfs interface and file hierarchy used by PMT devices.
For more information, see:
<file:Documentation/ABI/testing/sysfs-class-intel_pmt>
To compile this driver as a module, choose M here: the module
will be called intel_pmt_class.
config INTEL_PMT_TELEMETRY
tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"
depends on MFD_INTEL_PMT
select INTEL_PMT_CLASS
help
The Intel Platform Monitory Technology (PMT) Telemetry driver provides
access to hardware telemetry metrics on devices that support the
feature.
To compile this driver as a module, choose M here: the module
will be called intel_pmt_telemetry.
config INTEL_PMT_CRASHLOG
tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver"
depends on MFD_INTEL_PMT
select INTEL_PMT_CLASS
help
The Intel Platform Monitoring Technology (PMT) crashlog driver provides
access to hardware crashlog capabilities on devices that support the
feature.
To compile this driver as a module, choose M here: the module
will be called intel_pmt_crashlog.
config INTEL_PUNIT_IPC
tristate "Intel P-Unit IPC Driver"
help
This driver provides support for Intel P-Unit Mailbox IPC mechanism,
which is used to bridge the communications between kernel and P-Unit.
config INTEL_SCU_IPC
bool
@ -1297,18 +1046,6 @@ config INTEL_SCU_IPC_UTIL
low level access for debug work and updating the firmware. Say
N unless you will be doing this on an Intel MID platform.
config INTEL_TELEMETRY
tristate "Intel SoC Telemetry Driver"
depends on X86_64
depends on MFD_INTEL_PMC_BXT
depends on INTEL_PUNIT_IPC
help
This driver provides interfaces to configure and use
telemetry for INTEL SoC from APL onwards. It is also
used to get various SoC events and parameters
directly via debugfs files. Various tools may use
this interface for SoC state monitoring.
endif # X86_PLATFORM_DEVICES
config PMC_ATOM

View File

@ -10,8 +10,6 @@ obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o
# WMI drivers
obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
obj-$(CONFIG_INTEL_WMI_SBL_FW_UPDATE) += intel-wmi-sbl-fw-update.o
obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
@ -39,6 +37,9 @@ obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o
obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o
# Cisco/Meraki
obj-$(CONFIG_MERAKI_MX100) += meraki-mx100.o
# Dell
obj-$(CONFIG_X86_PLATFORM_DRIVERS_DELL) += dell/
@ -68,14 +69,6 @@ obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o
# Intel
obj-$(CONFIG_X86_PLATFORM_DRIVERS_INTEL) += intel/
obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o
obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
# MSI
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
obj-$(CONFIG_MSI_WMI) += msi-wmi.o
@ -118,27 +111,11 @@ obj-$(CONFIG_WIRELESS_HOTKEY) += wireless-hotkey.o
# Intel uncore drivers
obj-$(CONFIG_INTEL_IPS) += intel_ips.o
obj-$(CONFIG_INTEL_RST) += intel-rst.o
obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/
obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o
# Intel PMIC / PMC / P-Unit devices
obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o
obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o
obj-$(CONFIG_INTEL_PMT_CLASS) += intel_pmt_class.o
obj-$(CONFIG_INTEL_PMT_TELEMETRY) += intel_pmt_telemetry.o
obj-$(CONFIG_INTEL_PMT_CRASHLOG) += intel_pmt_crashlog.o
obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
obj-$(CONFIG_INTEL_SCU_PCI) += intel_scu_pcidrv.o
obj-$(CONFIG_INTEL_SCU_PLATFORM) += intel_scu_pltdrv.o
obj-$(CONFIG_INTEL_SCU_WDT) += intel_scu_wdt.o
obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
intel_telemetry_pltdrv.o \
intel_telemetry_debugfs.o
obj-$(CONFIG_PMC_ATOM) += pmc_atom.o

View File

@ -60,6 +60,11 @@ MODULE_LICENSE("GPL");
#define ACER_WMID_GET_THREEG_METHODID 10
#define ACER_WMID_SET_THREEG_METHODID 11
#define ACER_WMID_SET_GAMING_LED_METHODID 2
#define ACER_WMID_GET_GAMING_LED_METHODID 4
#define ACER_WMID_SET_GAMING_FAN_BEHAVIOR 14
#define ACER_WMID_SET_GAMING_MISC_SETTING_METHODID 22
/*
* Acer ACPI method GUIDs
*/
@ -68,6 +73,7 @@ MODULE_LICENSE("GPL");
#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
#define WMID_GUID2 "95764E09-FB56-4E83-B31A-37761F60994A"
#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
#define WMID_GUID4 "7A4DDFE7-5B5D-40B4-8595-4408E0CC7F56"
/*
* Acer ACPI event GUIDs
@ -81,6 +87,7 @@ MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
enum acer_wmi_event_ids {
WMID_HOTKEY_EVENT = 0x1,
WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5,
WMID_GAMING_TURBO_KEY_EVENT = 0x7,
};
static const struct key_entry acer_wmi_keymap[] __initconst = {
@ -215,6 +222,9 @@ struct hotkey_function_type_aa {
#define ACER_CAP_THREEG BIT(4)
#define ACER_CAP_SET_FUNCTION_MODE BIT(5)
#define ACER_CAP_KBD_DOCK BIT(6)
#define ACER_CAP_TURBO_OC BIT(7)
#define ACER_CAP_TURBO_LED BIT(8)
#define ACER_CAP_TURBO_FAN BIT(9)
/*
* Interface type flags
@ -301,6 +311,9 @@ struct quirk_entry {
u8 mailled;
s8 brightness;
u8 bluetooth;
u8 turbo;
u8 cpu_fans;
u8 gpu_fans;
};
static struct quirk_entry *quirks;
@ -312,6 +325,10 @@ static void __init set_quirks(void)
if (quirks->brightness)
interface->capability |= ACER_CAP_BRIGHTNESS;
if (quirks->turbo)
interface->capability |= ACER_CAP_TURBO_OC | ACER_CAP_TURBO_LED
| ACER_CAP_TURBO_FAN;
}
static int __init dmi_matched(const struct dmi_system_id *dmi)
@ -340,6 +357,12 @@ static struct quirk_entry quirk_acer_travelmate_2490 = {
.mailled = 1,
};
static struct quirk_entry quirk_acer_predator_ph315_53 = {
.turbo = 1,
.cpu_fans = 1,
.gpu_fans = 1,
};
/* This AMW0 laptop has no bluetooth */
static struct quirk_entry quirk_medion_md_98300 = {
.wireless = 1,
@ -507,6 +530,15 @@ static const struct dmi_system_id acer_quirks[] __initconst = {
},
.driver_data = &quirk_acer_travelmate_2490,
},
{
.callback = dmi_matched,
.ident = "Acer Predator PH315-53",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH315-53"),
},
.driver_data = &quirk_acer_predator_ph315_53,
},
{
.callback = set_force_caps,
.ident = "Acer Aspire Switch 10E SW3-016",
@ -1344,6 +1376,114 @@ static struct wmi_interface wmid_v2_interface = {
.type = ACER_WMID_v2,
};
/*
* WMID Gaming interface
*/
static acpi_status
WMI_gaming_execute_u64(u32 method_id, u64 in, u64 *out)
{
struct acpi_buffer input = { (acpi_size) sizeof(u64), (void *)(&in) };
struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
u32 tmp = 0;
acpi_status status;
status = wmi_evaluate_method(WMID_GUID4, 0, method_id, &input, &result);
if (ACPI_FAILURE(status))
return status;
obj = (union acpi_object *) result.pointer;
if (obj) {
if (obj->type == ACPI_TYPE_BUFFER) {
if (obj->buffer.length == sizeof(u32))
tmp = *((u32 *) obj->buffer.pointer);
else if (obj->buffer.length == sizeof(u64))
tmp = *((u64 *) obj->buffer.pointer);
} else if (obj->type == ACPI_TYPE_INTEGER) {
tmp = (u64) obj->integer.value;
}
}
if (out)
*out = tmp;
kfree(result.pointer);
return status;
}
static acpi_status WMID_gaming_set_u64(u64 value, u32 cap)
{
u32 method_id = 0;
if (!(interface->capability & cap))
return AE_BAD_PARAMETER;
switch (cap) {
case ACER_CAP_TURBO_LED:
method_id = ACER_WMID_SET_GAMING_LED_METHODID;
break;
case ACER_CAP_TURBO_FAN:
method_id = ACER_WMID_SET_GAMING_FAN_BEHAVIOR;
break;
case ACER_CAP_TURBO_OC:
method_id = ACER_WMID_SET_GAMING_MISC_SETTING_METHODID;
break;
default:
return AE_BAD_PARAMETER;
}
return WMI_gaming_execute_u64(method_id, value, NULL);
}
static acpi_status WMID_gaming_get_u64(u64 *value, u32 cap)
{
acpi_status status;
u64 result;
u64 input;
u32 method_id;
if (!(interface->capability & cap))
return AE_BAD_PARAMETER;
switch (cap) {
case ACER_CAP_TURBO_LED:
method_id = ACER_WMID_GET_GAMING_LED_METHODID;
input = 0x1;
break;
default:
return AE_BAD_PARAMETER;
}
status = WMI_gaming_execute_u64(method_id, input, &result);
if (ACPI_SUCCESS(status))
*value = (u64) result;
return status;
}
static void WMID_gaming_set_fan_mode(u8 fan_mode)
{
/* fan_mode = 1 is used for auto, fan_mode = 2 used for turbo*/
u64 gpu_fan_config1 = 0, gpu_fan_config2 = 0;
int i;
if (quirks->cpu_fans > 0)
gpu_fan_config2 |= 1;
for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i)
gpu_fan_config2 |= 1 << (i + 1);
for (i = 0; i < quirks->gpu_fans; ++i)
gpu_fan_config2 |= 1 << (i + 3);
if (quirks->cpu_fans > 0)
gpu_fan_config1 |= fan_mode;
for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i)
gpu_fan_config1 |= fan_mode << (2 * i + 2);
for (i = 0; i < quirks->gpu_fans; ++i)
gpu_fan_config1 |= fan_mode << (2 * i + 6);
WMID_gaming_set_u64(gpu_fan_config2 | gpu_fan_config1 << 16, ACER_CAP_TURBO_FAN);
}
/*
* Generic Device (interface-independent)
*/
@ -1575,6 +1715,41 @@ static int acer_gsensor_event(void)
return 0;
}
/*
* Predator series turbo button
*/
static int acer_toggle_turbo(void)
{
u64 turbo_led_state;
/* Get current state from turbo button */
if (ACPI_FAILURE(WMID_gaming_get_u64(&turbo_led_state, ACER_CAP_TURBO_LED)))
return -1;
if (turbo_led_state) {
/* Turn off turbo led */
WMID_gaming_set_u64(0x1, ACER_CAP_TURBO_LED);
/* Set FAN mode to auto */
WMID_gaming_set_fan_mode(0x1);
/* Set OC to normal */
WMID_gaming_set_u64(0x5, ACER_CAP_TURBO_OC);
WMID_gaming_set_u64(0x7, ACER_CAP_TURBO_OC);
} else {
/* Turn on turbo led */
WMID_gaming_set_u64(0x10001, ACER_CAP_TURBO_LED);
/* Set FAN mode to turbo */
WMID_gaming_set_fan_mode(0x2);
/* Set OC to turbo mode */
WMID_gaming_set_u64(0x205, ACER_CAP_TURBO_OC);
WMID_gaming_set_u64(0x207, ACER_CAP_TURBO_OC);
}
return turbo_led_state;
}
/*
* Switch series keyboard dock status
*/
@ -1872,6 +2047,10 @@ static void acer_wmi_notify(u32 value, void *context)
acer_gsensor_event();
acer_kbd_dock_event(&return_value);
break;
case WMID_GAMING_TURBO_KEY_EVENT:
if (return_value.key_num == 0x4)
acer_toggle_turbo();
break;
default:
pr_warn("Unknown function number - %d - %d\n",
return_value.function, return_value.key_num);

View File

@ -26,6 +26,7 @@
#include <linux/rfkill.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/platform_profile.h>
#include <linux/power_supply.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
@ -210,12 +211,24 @@ struct asus_wmi {
u8 fan_boost_mode_mask;
u8 fan_boost_mode;
bool egpu_enable_available; // 0 = enable
bool egpu_enable;
bool dgpu_disable_available;
bool dgpu_disable;
bool throttle_thermal_policy_available;
u8 throttle_thermal_policy_mode;
struct platform_profile_handler platform_profile_handler;
bool platform_profile_support;
// The RSOC controls the maximum charging percentage.
bool battery_rsoc_available;
bool panel_overdrive_available;
bool panel_overdrive;
struct hotplug_slot hotplug_slot;
struct mutex hotplug_lock;
struct mutex wmi_lock;
@ -424,6 +437,181 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus)
}
}
/* dGPU ********************************************************************/
static int dgpu_disable_check_present(struct asus_wmi *asus)
{
u32 result;
int err;
asus->dgpu_disable_available = false;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_DGPU, &result);
if (err) {
if (err == -ENODEV)
return 0;
return err;
}
if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
asus->dgpu_disable_available = true;
asus->dgpu_disable = result & ASUS_WMI_DSTS_STATUS_BIT;
}
return 0;
}
static int dgpu_disable_write(struct asus_wmi *asus)
{
u32 retval;
u8 value;
int err;
/* Don't rely on type conversion */
value = asus->dgpu_disable ? 1 : 0;
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, value, &retval);
if (err) {
pr_warn("Failed to set dgpu disable: %d\n", err);
return err;
}
if (retval > 1) {
pr_warn("Failed to set dgpu disable (retval): 0x%x\n", retval);
return -EIO;
}
sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable");
return 0;
}
static ssize_t dgpu_disable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct asus_wmi *asus = dev_get_drvdata(dev);
u8 mode = asus->dgpu_disable;
return sysfs_emit(buf, "%d\n", mode);
}
/*
* A user may be required to store the value twice, typcial store first, then
* rescan PCI bus to activate power, then store a second time to save correctly.
* The reason for this is that an extra code path in the ACPI is enabled when
* the device and bus are powered.
*/
static ssize_t dgpu_disable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
bool disable;
int result;
struct asus_wmi *asus = dev_get_drvdata(dev);
result = kstrtobool(buf, &disable);
if (result)
return result;
asus->dgpu_disable = disable;
result = dgpu_disable_write(asus);
if (result)
return result;
return count;
}
static DEVICE_ATTR_RW(dgpu_disable);
/* eGPU ********************************************************************/
static int egpu_enable_check_present(struct asus_wmi *asus)
{
u32 result;
int err;
asus->egpu_enable_available = false;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_EGPU, &result);
if (err) {
if (err == -ENODEV)
return 0;
return err;
}
if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
asus->egpu_enable_available = true;
asus->egpu_enable = result & ASUS_WMI_DSTS_STATUS_BIT;
}
return 0;
}
static int egpu_enable_write(struct asus_wmi *asus)
{
u32 retval;
u8 value;
int err;
/* Don't rely on type conversion */
value = asus->egpu_enable ? 1 : 0;
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, value, &retval);
if (err) {
pr_warn("Failed to set egpu disable: %d\n", err);
return err;
}
if (retval > 1) {
pr_warn("Failed to set egpu disable (retval): 0x%x\n", retval);
return -EIO;
}
sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable");
return 0;
}
static ssize_t egpu_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct asus_wmi *asus = dev_get_drvdata(dev);
bool mode = asus->egpu_enable;
return sysfs_emit(buf, "%d\n", mode);
}
/* The ACPI call to enable the eGPU also disables the internal dGPU */
static ssize_t egpu_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
bool enable;
int result;
struct asus_wmi *asus = dev_get_drvdata(dev);
result = kstrtobool(buf, &enable);
if (result)
return result;
asus->egpu_enable = enable;
result = egpu_enable_write(asus);
if (result)
return result;
/* Ensure that the kernel status of dgpu is updated */
result = dgpu_disable_check_present(asus);
if (result)
return result;
return count;
}
static DEVICE_ATTR_RW(egpu_enable);
/* Battery ********************************************************************/
/* The battery maximum charging percentage */
@ -1221,6 +1409,87 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
return result;
}
/* Panel Overdrive ************************************************************/
static int panel_od_check_present(struct asus_wmi *asus)
{
u32 result;
int err;
asus->panel_overdrive_available = false;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_PANEL_OD, &result);
if (err) {
if (err == -ENODEV)
return 0;
return err;
}
if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
asus->panel_overdrive_available = true;
asus->panel_overdrive = result & ASUS_WMI_DSTS_STATUS_BIT;
}
return 0;
}
static int panel_od_write(struct asus_wmi *asus)
{
u32 retval;
u8 value;
int err;
/* Don't rely on type conversion */
value = asus->panel_overdrive ? 1 : 0;
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PANEL_OD, value, &retval);
if (err) {
pr_warn("Failed to set panel overdrive: %d\n", err);
return err;
}
if (retval > 1) {
pr_warn("Failed to set panel overdrive (retval): 0x%x\n", retval);
return -EIO;
}
sysfs_notify(&asus->platform_device->dev.kobj, NULL, "panel_od");
return 0;
}
static ssize_t panel_od_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct asus_wmi *asus = dev_get_drvdata(dev);
return sysfs_emit(buf, "%d\n", asus->panel_overdrive);
}
static ssize_t panel_od_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
bool overdrive;
int result;
struct asus_wmi *asus = dev_get_drvdata(dev);
result = kstrtobool(buf, &overdrive);
if (result)
return result;
asus->panel_overdrive = overdrive;
result = panel_od_write(asus);
if (result)
return result;
return count;
}
static DEVICE_ATTR_RW(panel_od);
/* Quirks *********************************************************************/
static void asus_wmi_set_xusb2pr(struct asus_wmi *asus)
@ -1838,12 +2107,23 @@ static int throttle_thermal_policy_set_default(struct asus_wmi *asus)
static int throttle_thermal_policy_switch_next(struct asus_wmi *asus)
{
u8 new_mode = asus->throttle_thermal_policy_mode + 1;
int err;
if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
asus->throttle_thermal_policy_mode = new_mode;
return throttle_thermal_policy_write(asus);
err = throttle_thermal_policy_write(asus);
if (err)
return err;
/*
* Ensure that platform_profile updates userspace with the change to ensure
* that platform_profile and throttle_thermal_policy_mode are in sync.
*/
platform_profile_notify();
return 0;
}
static ssize_t throttle_thermal_policy_show(struct device *dev,
@ -1859,9 +2139,10 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int result;
u8 new_mode;
struct asus_wmi *asus = dev_get_drvdata(dev);
u8 new_mode;
int result;
int err;
result = kstrtou8(buf, 10, &new_mode);
if (result < 0)
@ -1871,7 +2152,15 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
return -EINVAL;
asus->throttle_thermal_policy_mode = new_mode;
throttle_thermal_policy_write(asus);
err = throttle_thermal_policy_write(asus);
if (err)
return err;
/*
* Ensure that platform_profile updates userspace with the change to ensure
* that platform_profile and throttle_thermal_policy_mode are in sync.
*/
platform_profile_notify();
return count;
}
@ -1879,6 +2168,91 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
// Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent
static DEVICE_ATTR_RW(throttle_thermal_policy);
/* Platform profile ***********************************************************/
static int platform_profile_get(struct platform_profile_handler *pprof,
enum platform_profile_option *profile)
{
struct asus_wmi *asus;
int tp;
asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
tp = asus->throttle_thermal_policy_mode;
switch (tp) {
case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:
*profile = PLATFORM_PROFILE_BALANCED;
break;
case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST:
*profile = PLATFORM_PROFILE_PERFORMANCE;
break;
case ASUS_THROTTLE_THERMAL_POLICY_SILENT:
*profile = PLATFORM_PROFILE_QUIET;
break;
default:
return -EINVAL;
}
return 0;
}
static int platform_profile_set(struct platform_profile_handler *pprof,
enum platform_profile_option profile)
{
struct asus_wmi *asus;
int tp;
asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
switch (profile) {
case PLATFORM_PROFILE_PERFORMANCE:
tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;
break;
case PLATFORM_PROFILE_BALANCED:
tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
break;
case PLATFORM_PROFILE_QUIET:
tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;
break;
default:
return -EOPNOTSUPP;
}
asus->throttle_thermal_policy_mode = tp;
return throttle_thermal_policy_write(asus);
}
static int platform_profile_setup(struct asus_wmi *asus)
{
struct device *dev = &asus->platform_device->dev;
int err;
/*
* Not an error if a component platform_profile relies on is unavailable
* so early return, skipping the setup of platform_profile.
*/
if (!asus->throttle_thermal_policy_available)
return 0;
dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
asus->platform_profile_handler.profile_get = platform_profile_get;
asus->platform_profile_handler.profile_set = platform_profile_set;
set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
set_bit(PLATFORM_PROFILE_BALANCED,
asus->platform_profile_handler.choices);
set_bit(PLATFORM_PROFILE_PERFORMANCE,
asus->platform_profile_handler.choices);
err = platform_profile_register(&asus->platform_profile_handler);
if (err)
return err;
asus->platform_profile_support = true;
return 0;
}
/* Backlight ******************************************************************/
static int read_backlight_power(struct asus_wmi *asus)
@ -2328,10 +2702,13 @@ static struct attribute *platform_attributes[] = {
&dev_attr_camera.attr,
&dev_attr_cardr.attr,
&dev_attr_touchpad.attr,
&dev_attr_egpu_enable.attr,
&dev_attr_dgpu_disable.attr,
&dev_attr_lid_resume.attr,
&dev_attr_als_enable.attr,
&dev_attr_fan_boost_mode.attr,
&dev_attr_throttle_thermal_policy.attr,
&dev_attr_panel_od.attr,
NULL
};
@ -2353,10 +2730,16 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
devid = ASUS_WMI_DEVID_LID_RESUME;
else if (attr == &dev_attr_als_enable.attr)
devid = ASUS_WMI_DEVID_ALS_ENABLE;
else if (attr == &dev_attr_egpu_enable.attr)
ok = asus->egpu_enable_available;
else if (attr == &dev_attr_dgpu_disable.attr)
ok = asus->dgpu_disable_available;
else if (attr == &dev_attr_fan_boost_mode.attr)
ok = asus->fan_boost_mode_available;
else if (attr == &dev_attr_throttle_thermal_policy.attr)
ok = asus->throttle_thermal_policy_available;
else if (attr == &dev_attr_panel_od.attr)
ok = asus->panel_overdrive_available;
if (devid != -1)
ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
@ -2612,6 +2995,14 @@ static int asus_wmi_add(struct platform_device *pdev)
if (err)
goto fail_platform;
err = egpu_enable_check_present(asus);
if (err)
goto fail_egpu_enable;
err = dgpu_disable_check_present(asus);
if (err)
goto fail_dgpu_disable;
err = fan_boost_mode_check_present(asus);
if (err)
goto fail_fan_boost_mode;
@ -2622,6 +3013,14 @@ static int asus_wmi_add(struct platform_device *pdev)
else
throttle_thermal_policy_set_default(asus);
err = platform_profile_setup(asus);
if (err)
goto fail_platform_profile_setup;
err = panel_od_check_present(asus);
if (err)
goto fail_panel_od;
err = asus_wmi_sysfs_init(asus->platform_device);
if (err)
goto fail_sysfs;
@ -2707,8 +3106,14 @@ static int asus_wmi_add(struct platform_device *pdev)
asus_wmi_sysfs_exit(asus->platform_device);
fail_sysfs:
fail_throttle_thermal_policy:
fail_platform_profile_setup:
if (asus->platform_profile_support)
platform_profile_remove();
fail_fan_boost_mode:
fail_egpu_enable:
fail_dgpu_disable:
fail_platform:
fail_panel_od:
kfree(asus);
return err;
}
@ -2728,6 +3133,9 @@ static int asus_wmi_remove(struct platform_device *device)
asus_fan_set_auto(asus);
asus_wmi_battery_exit(asus);
if (asus->platform_profile_support)
platform_profile_remove();
kfree(asus);
return 0;
}

View File

@ -140,7 +140,7 @@ config DELL_SMBIOS_SMM
config DELL_SMO8800
tristate "Dell Latitude freefall driver (ACPI SMO88XX)"
default m
depends on ACPI
depends on ACPI || COMPILE_TEST
help
Say Y here if you want to support SMO88XX freefall devices
on Dell Latitude laptops.

View File

@ -278,9 +278,9 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd)
}
/* SMI requires CPU 0 */
get_online_cpus();
cpus_read_lock();
ret = smp_call_on_cpu(0, raise_smi, smi_cmd, true);
put_online_cpus();
cpus_read_unlock();
return ret;
}

View File

@ -24,37 +24,6 @@ static struct calling_interface_buffer *buffer;
static struct platform_device *platform_device;
static DEFINE_MUTEX(smm_mutex);
static const struct dmi_system_id dell_device_table[] __initconst = {
{
.ident = "Dell laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /*Notebook*/
},
},
{
.ident = "Dell Computer Corporation",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
},
},
{ }
};
MODULE_DEVICE_TABLE(dmi, dell_device_table);
static void parse_da_table(const struct dmi_header *dm)
{
struct calling_interface_structure *table =

View File

@ -69,9 +69,10 @@ static int run_smbios_call(struct wmi_device *wdev)
if (obj->type == ACPI_TYPE_INTEGER)
dev_dbg(&wdev->dev, "SMBIOS call failed: %llu\n",
obj->integer.value);
kfree(output.pointer);
return -EIO;
}
memcpy(&priv->buf->std, obj->buffer.pointer, obj->buffer.length);
memcpy(input.pointer, obj->buffer.pointer, obj->buffer.length);
dev_dbg(&wdev->dev, "result: [%08x,%08x,%08x,%08x]\n",
priv->buf->std.output[0], priv->buf->std.output[1],
priv->buf->std.output[2], priv->buf->std.output[3]);

View File

@ -10,13 +10,14 @@
#define DRIVER_NAME "smo8800"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
struct smo8800_device {
u32 irq; /* acpi device irq */
@ -44,37 +45,6 @@ static irqreturn_t smo8800_interrupt_thread(int irq, void *data)
return IRQ_HANDLED;
}
static acpi_status smo8800_get_resource(struct acpi_resource *resource,
void *context)
{
struct acpi_resource_extended_irq *irq;
if (resource->type != ACPI_RESOURCE_TYPE_EXTENDED_IRQ)
return AE_OK;
irq = &resource->data.extended_irq;
if (!irq || !irq->interrupt_count)
return AE_OK;
*((u32 *)context) = irq->interrupts[0];
return AE_CTRL_TERMINATE;
}
static u32 smo8800_get_irq(struct acpi_device *device)
{
u32 irq = 0;
acpi_status status;
status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
smo8800_get_resource, &irq);
if (ACPI_FAILURE(status)) {
dev_err(&device->dev, "acpi_walk_resources failed\n");
return 0;
}
return irq;
}
static ssize_t smo8800_misc_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
@ -136,7 +106,7 @@ static const struct file_operations smo8800_misc_fops = {
.release = smo8800_misc_release,
};
static int smo8800_add(struct acpi_device *device)
static int smo8800_probe(struct platform_device *device)
{
int err;
struct smo8800_device *smo8800;
@ -160,14 +130,12 @@ static int smo8800_add(struct acpi_device *device)
return err;
}
device->driver_data = smo8800;
platform_set_drvdata(device, smo8800);
smo8800->irq = smo8800_get_irq(device);
if (!smo8800->irq) {
dev_err(&device->dev, "failed to obtain IRQ\n");
err = -EINVAL;
err = platform_get_irq(device, 0);
if (err < 0)
goto error;
}
smo8800->irq = err;
err = request_threaded_irq(smo8800->irq, smo8800_interrupt_quick,
smo8800_interrupt_thread,
@ -189,9 +157,9 @@ static int smo8800_add(struct acpi_device *device)
return err;
}
static int smo8800_remove(struct acpi_device *device)
static int smo8800_remove(struct platform_device *device)
{
struct smo8800_device *smo8800 = device->driver_data;
struct smo8800_device *smo8800 = platform_get_drvdata(device);
free_irq(smo8800->irq, smo8800);
misc_deregister(&smo8800->miscdev);
@ -211,21 +179,17 @@ static const struct acpi_device_id smo8800_ids[] = {
{ "SMO8831", 0 },
{ "", 0 },
};
MODULE_DEVICE_TABLE(acpi, smo8800_ids);
static struct acpi_driver smo8800_driver = {
.name = DRIVER_NAME,
.class = "Latitude",
.ids = smo8800_ids,
.ops = {
.add = smo8800_add,
.remove = smo8800_remove,
static struct platform_driver smo8800_driver = {
.probe = smo8800_probe,
.remove = smo8800_remove,
.driver = {
.name = DRIVER_NAME,
.acpi_match_table = smo8800_ids,
},
.owner = THIS_MODULE,
};
module_acpi_driver(smo8800_driver);
module_platform_driver(smo8800_driver);
MODULE_DESCRIPTION("Dell Latitude freefall driver (ACPI SMO88XX)");
MODULE_LICENSE("GPL");

View File

@ -17,30 +17,6 @@
#include <linux/acpi.h>
#include <linux/i2c.h>
static int dual_accel_i2c_resource_count(struct acpi_resource *ares, void *data)
{
struct acpi_resource_i2c_serialbus *sb;
int *count = data;
if (i2c_acpi_get_i2c_resource(ares, &sb))
*count = *count + 1;
return 1;
}
static int dual_accel_i2c_client_count(struct acpi_device *adev)
{
int ret, count = 0;
LIST_HEAD(r);
ret = acpi_dev_get_resources(adev, &r, dual_accel_i2c_resource_count, &count);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&r);
return count;
}
static bool dual_accel_detect_bosc0200(void)
{
struct acpi_device *adev;
@ -50,7 +26,7 @@ static bool dual_accel_detect_bosc0200(void)
if (!adev)
return false;
count = dual_accel_i2c_client_count(adev);
count = i2c_acpi_client_count(adev);
acpi_dev_put(adev);

View File

@ -28,9 +28,6 @@
#include <linux/serio.h>
#include "../../misc/lis3lv02d/lis3lv02d.h"
#define DRIVER_NAME "hp_accel"
#define ACPI_MDPS_CLASS "accelerometer"
/* Delayed LEDs infrastructure ------------------------------------ */
/* Special LED class that can defer work */
@ -78,23 +75,14 @@ static const struct acpi_device_id lis3lv02d_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
/**
* lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
* lis3lv02d_acpi_init - initialize the device for ACPI
* @lis3: pointer to the device struct
*
* Returns 0 on success.
*/
static int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
{
struct acpi_device *dev = lis3->bus_priv;
if (!lis3->init_required)
return 0;
if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
NULL, NULL) != AE_OK)
return -EINVAL;
return 0;
}
@ -278,30 +266,6 @@ static struct delayed_led_classdev hpled_led = {
.set_brightness = hpled_set,
};
static acpi_status
lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
{
if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
struct acpi_resource_extended_irq *irq;
u32 *device_irq = context;
irq = &resource->data.extended_irq;
*device_irq = irq->interrupts[0];
}
return AE_OK;
}
static void lis3lv02d_enum_resources(struct acpi_device *device)
{
acpi_status status;
status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
lis3lv02d_get_resource, &lis3_dev.irq);
if (ACPI_FAILURE(status))
printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
}
static bool hp_accel_i8042_filter(unsigned char data, unsigned char str,
struct serio *port)
{
@ -331,23 +295,19 @@ static bool hp_accel_i8042_filter(unsigned char data, unsigned char str,
return false;
}
static int lis3lv02d_add(struct acpi_device *device)
static int lis3lv02d_probe(struct platform_device *device)
{
int ret;
if (!device)
return -EINVAL;
lis3_dev.bus_priv = device;
lis3_dev.bus_priv = ACPI_COMPANION(&device->dev);
lis3_dev.init = lis3lv02d_acpi_init;
lis3_dev.read = lis3lv02d_acpi_read;
lis3_dev.write = lis3lv02d_acpi_write;
strcpy(acpi_device_name(device), DRIVER_NAME);
strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
device->driver_data = &lis3_dev;
/* obtain IRQ number of our device from ACPI */
lis3lv02d_enum_resources(device);
ret = platform_get_irq_optional(device, 0);
if (ret > 0)
lis3_dev.irq = ret;
/* If possible use a "standard" axes order */
if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
@ -359,7 +319,6 @@ static int lis3lv02d_add(struct acpi_device *device)
}
/* call the core layer do its init */
lis3_dev.init_required = true;
ret = lis3lv02d_init_device(&lis3_dev);
if (ret)
return ret;
@ -381,11 +340,8 @@ static int lis3lv02d_add(struct acpi_device *device)
return ret;
}
static int lis3lv02d_remove(struct acpi_device *device)
static int lis3lv02d_remove(struct platform_device *device)
{
if (!device)
return -EINVAL;
i8042_remove_filter(hp_accel_i8042_filter);
lis3lv02d_joystick_disable(&lis3_dev);
lis3lv02d_poweroff(&lis3_dev);
@ -396,7 +352,6 @@ static int lis3lv02d_remove(struct acpi_device *device)
return lis3lv02d_remove_fs(&lis3_dev);
}
#ifdef CONFIG_PM_SLEEP
static int lis3lv02d_suspend(struct device *dev)
{
@ -407,14 +362,12 @@ static int lis3lv02d_suspend(struct device *dev)
static int lis3lv02d_resume(struct device *dev)
{
lis3_dev.init_required = false;
lis3lv02d_poweron(&lis3_dev);
return 0;
}
static int lis3lv02d_restore(struct device *dev)
{
lis3_dev.init_required = true;
lis3lv02d_poweron(&lis3_dev);
return 0;
}
@ -434,17 +387,16 @@ static const struct dev_pm_ops hp_accel_pm = {
#endif
/* For the HP MDPS aka 3D Driveguard */
static struct acpi_driver lis3lv02d_driver = {
.name = DRIVER_NAME,
.class = ACPI_MDPS_CLASS,
.ids = lis3lv02d_device_ids,
.ops = {
.add = lis3lv02d_add,
.remove = lis3lv02d_remove,
static struct platform_driver lis3lv02d_driver = {
.probe = lis3lv02d_probe,
.remove = lis3lv02d_remove,
.driver = {
.name = "hp_accel",
.pm = HP_ACCEL_PM,
.acpi_match_table = lis3lv02d_device_ids,
},
.drv.pm = HP_ACCEL_PM,
};
module_acpi_driver(lis3lv02d_driver);
module_platform_driver(lis3lv02d_driver);
MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");

View File

@ -32,31 +32,6 @@ struct i2c_multi_inst_data {
struct i2c_client *clients[];
};
static int i2c_multi_inst_count(struct acpi_resource *ares, void *data)
{
struct acpi_resource_i2c_serialbus *sb;
int *count = data;
if (i2c_acpi_get_i2c_resource(ares, &sb))
*count = *count + 1;
return 1;
}
static int i2c_multi_inst_count_resources(struct acpi_device *adev)
{
LIST_HEAD(r);
int count = 0;
int ret;
ret = acpi_dev_get_resources(adev, &r, i2c_multi_inst_count, &count);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&r);
return count;
}
static int i2c_multi_inst_probe(struct platform_device *pdev)
{
struct i2c_multi_inst_data *multi;
@ -76,7 +51,7 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
adev = ACPI_COMPANION(dev);
/* Count number of clients to instantiate */
ret = i2c_multi_inst_count_resources(adev);
ret = i2c_acpi_client_count(adev);
if (ret < 0)
return ret;

View File

@ -41,6 +41,7 @@
static const char *const ideapad_wmi_fnesc_events[] = {
"26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */
"56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */
"8FC0DE0C-B4E4-43FD-B0F3-8871711C1294", /* Legion 5 */
};
#endif
@ -1459,11 +1460,19 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
static void ideapad_wmi_notify(u32 value, void *context)
{
struct ideapad_private *priv = context;
unsigned long result;
switch (value) {
case 128:
ideapad_input_report(priv, value);
break;
case 208:
if (!eval_hals(priv->adev->handle, &result)) {
bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
}
break;
default:
dev_info(&priv->platform_device->dev,
"Unknown WMI event: %u\n", value);

View File

@ -16,7 +16,156 @@ menuconfig X86_PLATFORM_DRIVERS_INTEL
if X86_PLATFORM_DRIVERS_INTEL
source "drivers/platform/x86/intel/atomisp2/Kconfig"
source "drivers/platform/x86/intel/int1092/Kconfig"
source "drivers/platform/x86/intel/int33fe/Kconfig"
source "drivers/platform/x86/intel/int3472/Kconfig"
source "drivers/platform/x86/intel/pmc/Kconfig"
source "drivers/platform/x86/intel/pmt/Kconfig"
source "drivers/platform/x86/intel/speed_select_if/Kconfig"
source "drivers/platform/x86/intel/telemetry/Kconfig"
source "drivers/platform/x86/intel/wmi/Kconfig"
config INTEL_HID_EVENT
tristate "Intel HID Event"
depends on ACPI
depends on INPUT
depends on I2C
select INPUT_SPARSEKMAP
help
This driver provides support for the Intel HID Event hotkey interface.
Some laptops require this driver for hotkey support.
To compile this driver as a module, choose M here: the module will
be called intel_hid.
config INTEL_VBTN
tristate "Intel Virtual Button"
depends on ACPI
depends on INPUT
depends on I2C
select INPUT_SPARSEKMAP
help
This driver provides support for the Intel Virtual Button interface.
Some laptops require this driver for power button support.
To compile this driver as a module, choose M here: the module will
be called intel_vbtn.
config INTEL_INT0002_VGPIO
tristate "Intel ACPI INT0002 Virtual GPIO driver"
depends on GPIOLIB && ACPI && PM_SLEEP
select GPIOLIB_IRQCHIP
help
Some peripherals on Bay Trail and Cherry Trail platforms signal a
Power Management Event (PME) to the Power Management Controller (PMC)
to wakeup the system. When this happens software needs to explicitly
clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
IRQ storm on IRQ 9.
This is modelled in ACPI through the INT0002 ACPI device, which is
called a "Virtual GPIO controller" in ACPI because it defines the
event handler to call when the PME triggers through _AEI and _L02
methods as would be done for a real GPIO interrupt in ACPI.
To compile this driver as a module, choose M here: the module will
be called intel_int0002_vgpio.
config INTEL_OAKTRAIL
tristate "Intel Oaktrail Platform Extras"
depends on ACPI
depends on ACPI_VIDEO || ACPI_VIDEO=n
depends on RFKILL && BACKLIGHT_CLASS_DEVICE && ACPI
help
Intel Oaktrail platform need this driver to provide interfaces to
enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
here; it will only load on supported platforms.
config INTEL_BXTWC_PMIC_TMU
tristate "Intel Broxton Whiskey Cove TMU Driver"
depends on INTEL_SOC_PMIC_BXTWC
depends on MFD_INTEL_PMC_BXT
select REGMAP
help
Select this driver to use Intel Broxton Whiskey Cove PMIC TMU feature.
This driver enables the alarm wakeup functionality in the TMU unit of
Whiskey Cove PMIC.
config INTEL_CHTDC_TI_PWRBTN
tristate "Intel Cherry Trail Dollar Cove TI power button driver"
depends on INTEL_SOC_PMIC_CHTDC_TI
depends on INPUT
help
This option adds a power button driver for Dollar Cove TI
PMIC on Intel Cherry Trail devices.
To compile this driver as a module, choose M here: the module
will be called intel_chtdc_ti_pwrbtn.
config INTEL_MRFLD_PWRBTN
tristate "Intel Merrifield Basin Cove power button driver"
depends on INTEL_SOC_PMIC_MRFLD
depends on INPUT
help
This option adds a power button driver for Basin Cove PMIC
on Intel Merrifield devices.
To compile this driver as a module, choose M here: the module
will be called intel_mrfld_pwrbtn.
config INTEL_PUNIT_IPC
tristate "Intel P-Unit IPC Driver"
help
This driver provides support for Intel P-Unit Mailbox IPC mechanism,
which is used to bridge the communications between kernel and P-Unit.
config INTEL_RST
tristate "Intel Rapid Start Technology Driver"
depends on ACPI
help
This driver provides support for modifying parameters on systems
equipped with Intel's Rapid Start Technology. When put in an ACPI
sleep state, these devices will wake after either a configured
timeout or when the system battery reaches a critical state,
automatically copying memory contents to disk. On resume, the
firmware will copy the memory contents back to RAM and resume the OS
as usual.
config INTEL_SMARTCONNECT
tristate "Intel Smart Connect disabling driver"
depends on ACPI
help
Intel Smart Connect is a technology intended to permit devices to
update state by resuming for a short period of time at regular
intervals. If a user enables this functionality under Windows and
then reboots into Linux, the system may remain configured to resume
on suspend. In the absence of any userspace to support it, the system
will then remain awake until something triggers another suspend.
This driver checks to determine whether the device has Intel Smart
Connect enabled, and if so disables it.
config INTEL_TURBO_MAX_3
bool "Intel Turbo Boost Max Technology 3.0 enumeration driver"
depends on X86_64 && SCHED_MC_PRIO
help
This driver reads maximum performance ratio of each CPU and set up
the scheduler priority metrics. In this way scheduler can prefer
CPU with higher performance to schedule tasks.
This driver is only required when the system is not using Hardware
P-States (HWP). In HWP mode, priority can be read from ACPI tables.
config INTEL_UNCORE_FREQ_CONTROL
tristate "Intel Uncore frequency control driver"
depends on X86_64
help
This driver allows control of Uncore frequency limits on
supported server platforms.
Uncore frequency controls RING/LLC (last-level cache) clocks.
To compile this driver as a module, choose M here: the module
will be called intel-uncore-frequency.
endif # X86_PLATFORM_DRIVERS_INTEL

View File

@ -4,5 +4,44 @@
# Intel x86 Platform-Specific Drivers
#
obj-$(CONFIG_INTEL_ATOMISP2_PDX86) += atomisp2/
obj-$(CONFIG_INTEL_SAR_INT1092) += int1092/
obj-$(CONFIG_INTEL_CHT_INT33FE) += int33fe/
obj-$(CONFIG_INTEL_SKL_INT3472) += int3472/
obj-$(CONFIG_INTEL_PMC_CORE) += pmc/
obj-$(CONFIG_INTEL_PMT_CLASS) += pmt/
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += speed_select_if/
obj-$(CONFIG_INTEL_TELEMETRY) += telemetry/
obj-$(CONFIG_INTEL_WMI) += wmi/
# Intel input drivers
intel-hid-y := hid.o
obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
intel-vbtn-y := vbtn.o
obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
# Intel miscellaneous drivers
intel_int0002_vgpio-y := int0002_vgpio.o
obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
intel_oaktrail-y := oaktrail.o
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
# Intel PMIC / PMC / P-Unit drivers
intel_bxtwc_tmu-y := bxtwc_tmu.o
obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU) += intel_bxtwc_tmu.o
intel_chtdc_ti_pwrbtn-y := chtdc_ti_pwrbtn.o
obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
intel_mrfld_pwrbtn-y := mrfld_pwrbtn.o
obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
intel_punit_ipc-y := punit_ipc.o
obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
# Intel Uncore drivers
intel-rst-y := rst.o
obj-$(CONFIG_INTEL_RST) += intel-rst.o
intel-smartconnect-y := smartconnect.o
obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
intel_turbo_max_3-y := turbo_max_3.o
obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
intel-uncore-frequency-y := uncore-frequency.o
obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o

View File

@ -0,0 +1,43 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Intel x86 Platform Specific Drivers
#
config INTEL_ATOMISP2_PDX86
bool
config INTEL_ATOMISP2_LED
tristate "Intel AtomISP v2 camera LED driver"
depends on GPIOLIB && LEDS_GPIO
select INTEL_ATOMISP2_PDX86
help
Many Bay Trail and Cherry Trail devices come with a camera attached
to Intel's Image Signal Processor. Linux currently does not have a
driver for these, so they do not work as a camera. Some of these
camera's have a LED which is controlled through a GPIO.
Some of these devices have a firmware issue where the LED gets turned
on at boot. This driver will turn the LED off at boot and also allows
controlling the LED (repurposing it) through the sysfs LED interface.
Which GPIO is attached to the LED is usually not described in the
ACPI tables, so this driver contains per-system info about the GPIO
inside the driver, this means that this driver only works on systems
the driver knows about.
To compile this driver as a module, choose M here: the module
will be called intel_atomisp2_led.
config INTEL_ATOMISP2_PM
tristate "Intel AtomISP v2 dummy / power-management driver"
depends on PCI && IOSF_MBI && PM
depends on !INTEL_ATOMISP
select INTEL_ATOMISP2_PDX86
help
Power-management driver for Intel's Image Signal Processor found on
Bay Trail and Cherry Trail devices. This dummy driver's sole purpose
is to turn the ISP off (put it in D3) to save power and to allow
entering of S0ix modes.
To compile this driver as a module, choose M here: the module
will be called intel_atomisp2_pm.

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Intel x86 Platform Specific Drivers
#
intel_atomisp2_led-y := led.o
obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o
intel_atomisp2_pm-y += pm.o
obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o

View File

@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
#include "dual_accel_detect.h"
#include "../dual_accel_detect.h"
/* When NOT in tablet mode, VGBS returns with the flag 0x40 */
#define TABLET_MODE_FLAG BIT(6)

View File

@ -0,0 +1,14 @@
config INTEL_SAR_INT1092
tristate "Intel Specific Absorption Rate Driver"
depends on ACPI
help
This driver helps to limit the exposure of human body to RF frequency by
providing information to userspace application that will inform the Intel
M.2 modem to regulate the RF power based on SAR data obtained from the
sensors captured in the BIOS. ACPI interface exposes this data from the BIOS
to SAR driver. The front end application in userspace will interact with SAR
driver to obtain information like the device mode, Antenna index, baseband index,
SAR table index and use available communication like MBIM interface to enable
data communication to modem for RF power regulation. Enable this config when
given platform needs to support "Dynamic SAR" configuration for a modem available
on the platform.

View File

@ -0,0 +1 @@
obj-$(CONFIG_INTEL_SAR_INT1092) += intel_sar.o

View File

@ -0,0 +1,316 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, Intel Corporation.
*/
#include <linux/acpi.h>
#include <linux/kobject.h>
#include <linux/platform_device.h>
#include <linux/sysfs.h>
#include "intel_sar.h"
/**
* get_int_value: Retrieve integer values from ACPI Object
* @obj: acpi_object pointer which has the integer value
* @out: output pointer will get integer value
*
* Function is used to retrieve integer value from acpi object.
*
* Return:
* * 0 on success
* * -EIO if there is an issue in acpi_object passed.
*/
static int get_int_value(union acpi_object *obj, int *out)
{
if (!obj || obj->type != ACPI_TYPE_INTEGER)
return -EIO;
*out = (int)obj->integer.value;
return 0;
}
/**
* update_sar_data: sar data is updated based on regulatory mode
* @context: pointer to driver context structure
*
* sar_data is updated based on regulatory value
* context->reg_value will never exceed MAX_REGULATORY
*/
static void update_sar_data(struct wwan_sar_context *context)
{
struct wwan_device_mode_configuration *config =
&context->config_data[context->reg_value];
if (config->device_mode_info &&
context->sar_data.device_mode < config->total_dev_mode) {
struct wwan_device_mode_info *dev_mode =
&config->device_mode_info[context->sar_data.device_mode];
context->sar_data.antennatable_index = dev_mode->antennatable_index;
context->sar_data.bandtable_index = dev_mode->bandtable_index;
context->sar_data.sartable_index = dev_mode->sartable_index;
}
}
/**
* parse_package: parse acpi package for retrieving SAR information
* @context: pointer to driver context structure
* @item : acpi_object pointer
*
* Given acpi_object is iterated to retrieve information for each device mode.
* If a given package corresponding to a specific device mode is faulty, it is
* skipped and the specific entry in context structure will have the default value
* of zero. Decoding of subsequent device modes is realized by having "continue"
* statements in the for loop on encountering error in parsing given device mode.
*
* Return:
* AE_OK if success
* AE_ERROR on error
*/
static acpi_status parse_package(struct wwan_sar_context *context, union acpi_object *item)
{
struct wwan_device_mode_configuration *data;
int value, itr, reg;
union acpi_object *num;
num = &item->package.elements[0];
if (get_int_value(num, &value) || value < 0 || value >= MAX_REGULATORY)
return AE_ERROR;
reg = value;
data = &context->config_data[reg];
if (data->total_dev_mode > MAX_DEV_MODES || data->total_dev_mode == 0 ||
item->package.count <= data->total_dev_mode)
return AE_ERROR;
data->device_mode_info = kmalloc_array(data->total_dev_mode,
sizeof(struct wwan_device_mode_info), GFP_KERNEL);
if (!data->device_mode_info)
return AE_ERROR;
for (itr = 0; itr < data->total_dev_mode; itr++) {
struct wwan_device_mode_info temp = { 0 };
num = &item->package.elements[itr + 1];
if (num->type != ACPI_TYPE_PACKAGE || num->package.count < TOTAL_DATA)
continue;
if (get_int_value(&num->package.elements[0], &temp.device_mode))
continue;
if (get_int_value(&num->package.elements[1], &temp.bandtable_index))
continue;
if (get_int_value(&num->package.elements[2], &temp.antennatable_index))
continue;
if (get_int_value(&num->package.elements[3], &temp.sartable_index))
continue;
data->device_mode_info[itr] = temp;
}
return AE_OK;
}
/**
* sar_get_device_mode: Extraction of information from BIOS via DSM calls
* @device: ACPI device for which to retrieve the data
*
* Retrieve the current device mode information from the BIOS.
*
* Return:
* AE_OK on success
* AE_ERROR on error
*/
static acpi_status sar_get_device_mode(struct platform_device *device)
{
struct wwan_sar_context *context = dev_get_drvdata(&device->dev);
acpi_status status = AE_OK;
union acpi_object *out;
u32 rev = 0;
int value;
out = acpi_evaluate_dsm(context->handle, &context->guid, rev,
COMMAND_ID_DEV_MODE, NULL);
if (get_int_value(out, &value)) {
dev_err(&device->dev, "DSM cmd:%d Failed to retrieve value\n", COMMAND_ID_DEV_MODE);
status = AE_ERROR;
goto dev_mode_error;
}
context->sar_data.device_mode = value;
update_sar_data(context);
sysfs_notify(&device->dev.kobj, NULL, SYSFS_DATANAME);
dev_mode_error:
ACPI_FREE(out);
return status;
}
static const struct acpi_device_id sar_device_ids[] = {
{ "INTC1092", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, sar_device_ids);
static ssize_t intc_data_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct wwan_sar_context *context = dev_get_drvdata(dev);
return sysfs_emit(buf, "%d %d %d %d\n", context->sar_data.device_mode,
context->sar_data.bandtable_index,
context->sar_data.antennatable_index,
context->sar_data.sartable_index);
}
static DEVICE_ATTR_RO(intc_data);
static ssize_t intc_reg_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct wwan_sar_context *context = dev_get_drvdata(dev);
return sysfs_emit(buf, "%d\n", context->reg_value);
}
static ssize_t intc_reg_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct wwan_sar_context *context = dev_get_drvdata(dev);
unsigned int value;
int read;
if (!count)
return -EINVAL;
read = kstrtouint(buf, 10, &value);
if (read < 0)
return read;
if (value >= MAX_REGULATORY)
return -EOVERFLOW;
context->reg_value = value;
update_sar_data(context);
sysfs_notify(&dev->kobj, NULL, SYSFS_DATANAME);
return count;
}
static DEVICE_ATTR_RW(intc_reg);
static struct attribute *intcsar_attrs[] = {
&dev_attr_intc_data.attr,
&dev_attr_intc_reg.attr,
NULL
};
static struct attribute_group intcsar_group = {
.attrs = intcsar_attrs,
};
static void sar_notify(acpi_handle handle, u32 event, void *data)
{
struct platform_device *device = data;
if (event == SAR_EVENT) {
if (sar_get_device_mode(device) != AE_OK)
dev_err(&device->dev, "sar_get_device_mode error");
}
}
static void sar_get_data(int reg, struct wwan_sar_context *context)
{
union acpi_object *out, req;
u32 rev = 0;
req.type = ACPI_TYPE_INTEGER;
req.integer.value = reg;
out = acpi_evaluate_dsm(context->handle, &context->guid, rev,
COMMAND_ID_CONFIG_TABLE, &req);
if (!out)
return;
if (out->type == ACPI_TYPE_PACKAGE && out->package.count >= 3 &&
out->package.elements[0].type == ACPI_TYPE_INTEGER &&
out->package.elements[1].type == ACPI_TYPE_INTEGER &&
out->package.elements[2].type == ACPI_TYPE_PACKAGE &&
out->package.elements[2].package.count > 0) {
context->config_data[reg].version = out->package.elements[0].integer.value;
context->config_data[reg].total_dev_mode =
out->package.elements[1].integer.value;
if (context->config_data[reg].total_dev_mode <= 0 ||
context->config_data[reg].total_dev_mode > MAX_DEV_MODES) {
ACPI_FREE(out);
return;
}
parse_package(context, &out->package.elements[2]);
}
ACPI_FREE(out);
}
static int sar_probe(struct platform_device *device)
{
struct wwan_sar_context *context;
int reg;
int result;
context = kzalloc(sizeof(*context), GFP_KERNEL);
if (!context)
return -ENOMEM;
context->sar_device = device;
context->handle = ACPI_HANDLE(&device->dev);
dev_set_drvdata(&device->dev, context);
result = guid_parse(SAR_DSM_UUID, &context->guid);
if (result) {
dev_err(&device->dev, "SAR UUID parse error: %d\n", result);
goto r_free;
}
for (reg = 0; reg < MAX_REGULATORY; reg++)
sar_get_data(reg, context);
if (sar_get_device_mode(device) != AE_OK) {
dev_err(&device->dev, "Failed to get device mode\n");
result = -EIO;
goto r_free;
}
result = sysfs_create_group(&device->dev.kobj, &intcsar_group);
if (result) {
dev_err(&device->dev, "sysfs creation failed\n");
goto r_free;
}
if (acpi_install_notify_handler(ACPI_HANDLE(&device->dev), ACPI_DEVICE_NOTIFY,
sar_notify, (void *)device) != AE_OK) {
dev_err(&device->dev, "Failed acpi_install_notify_handler\n");
result = -EIO;
goto r_sys;
}
return 0;
r_sys:
sysfs_remove_group(&device->dev.kobj, &intcsar_group);
r_free:
kfree(context);
return result;
}
static int sar_remove(struct platform_device *device)
{
struct wwan_sar_context *context = dev_get_drvdata(&device->dev);
int reg;
acpi_remove_notify_handler(ACPI_HANDLE(&device->dev),
ACPI_DEVICE_NOTIFY, sar_notify);
sysfs_remove_group(&device->dev.kobj, &intcsar_group);
for (reg = 0; reg < MAX_REGULATORY; reg++)
kfree(context->config_data[reg].device_mode_info);
kfree(context);
return 0;
}
static struct platform_driver sar_driver = {
.probe = sar_probe,
.remove = sar_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(sar_device_ids)
}
};
module_platform_driver(sar_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Platform device driver for INTEL MODEM BIOS SAR");
MODULE_AUTHOR("Shravan S <s.shravan@intel.com>");

View File

@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021, Intel Corporation.
*/
#ifndef INTEL_SAR_H
#define INTEL_SAR_H
#define COMMAND_ID_DEV_MODE 1
#define COMMAND_ID_CONFIG_TABLE 2
#define DRVNAME "intc_sar"
#define MAX_DEV_MODES 50
#define MAX_REGULATORY 3
#define SAR_DSM_UUID "82737E72-3A33-4C45-A9C7-57C0411A5F13"
#define SAR_EVENT 0x80
#define SYSFS_DATANAME "intc_data"
#define TOTAL_DATA 4
/**
* Structure wwan_device_mode_info - device mode information
* Holds the data that needs to be passed to userspace.
* The data is updated from the BIOS sensor information.
* @device_mode: Specific mode of the device
* @bandtable_index: Index of RF band
* @antennatable_index: Index of antenna
* @sartable_index: Index of SAR
*/
struct wwan_device_mode_info {
int device_mode;
int bandtable_index;
int antennatable_index;
int sartable_index;
};
/**
* Structure wwan_device_mode_configuration - device configuration
* Holds the data that is configured and obtained on probe event.
* The data is updated from the BIOS sensor information.
* @version: Mode configuration version
* @total_dev_mode: Total number of device modes
* @device_mode_info: pointer to structure wwan_device_mode_info
*/
struct wwan_device_mode_configuration {
int version;
int total_dev_mode;
struct wwan_device_mode_info *device_mode_info;
};
/**
* Structure wwan_supported_info - userspace datastore
* Holds the data that is obtained from userspace
* The data is updated from the userspace and send value back in the
* structure format that is mentioned here.
* @reg_mode_needed: regulatory mode set by user for tests
* @bios_table_revision: Version of SAR table
* @num_supported_modes: Total supported modes based on reg_mode
*/
struct wwan_supported_info {
int reg_mode_needed;
int bios_table_revision;
int num_supported_modes;
};
/**
* Structure wwan_sar_context - context of SAR
* Holds the complete context as long as the driver is in existence
* The context holds instance of the data used for different cases.
* @guid: Group id
* @handle: store acpi handle
* @reg_value: regulatory value
* Regulatory 0: FCC, 1: CE, 2: ISED
* @sar_device: platform_device type
* @sar_kobject: kobject for sysfs
* @supported_data: wwan_supported_info struct
* @sar_data: wwan_device_mode_info struct
* @config_data: wwan_device_mode_configuration array struct
*/
struct wwan_sar_context {
guid_t guid;
acpi_handle handle;
int reg_value;
struct platform_device *sar_device;
struct wwan_supported_info supported_data;
struct wwan_device_mode_info sar_data;
struct wwan_device_mode_configuration config_data[MAX_REGULATORY];
};
#endif /* INTEL_SAR_H */

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
intel_cht_int33fe-objs := intel_cht_int33fe_common.o \
intel_cht_int33fe-y := intel_cht_int33fe_common.o \
intel_cht_int33fe_typec.o \
intel_cht_int33fe_microb.o

View File

@ -16,33 +16,6 @@
#define EXPECTED_PTYPE 4
static int cht_int33fe_i2c_res_filter(struct acpi_resource *ares, void *data)
{
struct acpi_resource_i2c_serialbus *sb;
int *count = data;
if (i2c_acpi_get_i2c_resource(ares, &sb))
(*count)++;
return 1;
}
static int cht_int33fe_count_i2c_clients(struct device *dev)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
LIST_HEAD(resource_list);
int count = 0;
int ret;
ret = acpi_dev_get_resources(adev, &resource_list,
cht_int33fe_i2c_res_filter, &count);
acpi_dev_free_resource_list(&resource_list);
if (ret < 0)
return ret;
return count;
}
static int cht_int33fe_check_hw_type(struct device *dev)
{
unsigned long long ptyp;
@ -69,7 +42,7 @@ static int cht_int33fe_check_hw_type(struct device *dev)
return -ENODEV;
}
ret = cht_int33fe_count_i2c_clients(dev);
ret = i2c_acpi_client_count(ACPI_COMPANION(dev));
if (ret < 0)
return ret;

View File

@ -1,5 +1,5 @@
obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472.o
intel_skl_int3472-objs := intel_skl_int3472_common.o \
intel_skl_int3472-y := intel_skl_int3472_common.o \
intel_skl_int3472_discrete.o \
intel_skl_int3472_tps68470.o \
intel_skl_int3472_clk_and_regulator.o

View File

@ -0,0 +1,25 @@
# SPDX-License-Identifier: GPL-2.0
#
# Intel x86 Platform-Specific Drivers
#
config INTEL_PMC_CORE
tristate "Intel PMC Core driver"
depends on PCI
depends on ACPI
help
The Intel Platform Controller Hub for Intel Core SoCs provides access
to Power Management Controller registers via various interfaces. This
driver can utilize debugging capabilities and supported features as
exposed by the Power Management Controller. It also may perform some
tasks in the PMC in order to enable transition into the SLPS0 state.
It should be selected on all Intel platforms supported by the driver.
Supported features:
- SLP_S0_RESIDENCY counter
- PCH IP Power Gating status
- LTR Ignore / LTR Show
- MPHY/PLL gating status (Sunrisepoint PCH only)
- SLPS0 Debug registers (Cannonlake/Icelake PCH)
- Low Power Mode registers (Tigerlake and beyond)
- PMC quirks as needed to enable SLPS0/S0ix

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
#
# Intel x86 Platform-Specific Drivers
#
intel_pmc_core-y := core.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

View File

@ -31,7 +31,7 @@
#include <asm/msr.h>
#include <asm/tsc.h>
#include "intel_pmc_core.h"
#include "core.h"
#define ACPI_S0IX_DSM_UUID "57a6512e-3979-4e9d-9708-ff13b2508972"
#define ACPI_GET_LOW_MODE_REGISTERS 1
@ -645,6 +645,306 @@ static void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev)
ACPI_FREE(out_obj);
}
/* Alder Lake: PGD PFET Enable Ack Status Register(s) bitmap */
static const struct pmc_bit_map adl_pfear_map[] = {
{"SPI/eSPI", BIT(2)},
{"XHCI", BIT(3)},
{"SPA", BIT(4)},
{"SPB", BIT(5)},
{"SPC", BIT(6)},
{"GBE", BIT(7)},
{"SATA", BIT(0)},
{"HDA_PGD0", BIT(1)},
{"HDA_PGD1", BIT(2)},
{"HDA_PGD2", BIT(3)},
{"HDA_PGD3", BIT(4)},
{"SPD", BIT(5)},
{"LPSS", BIT(6)},
{"SMB", BIT(0)},
{"ISH", BIT(1)},
{"ITH", BIT(3)},
{"XDCI", BIT(1)},
{"DCI", BIT(2)},
{"CSE", BIT(3)},
{"CSME_KVM", BIT(4)},
{"CSME_PMT", BIT(5)},
{"CSME_CLINK", BIT(6)},
{"CSME_PTIO", BIT(7)},
{"CSME_USBR", BIT(0)},
{"CSME_SUSRAM", BIT(1)},
{"CSME_SMT1", BIT(2)},
{"CSME_SMS2", BIT(4)},
{"CSME_SMS1", BIT(5)},
{"CSME_RTC", BIT(6)},
{"CSME_PSF", BIT(7)},
{"CNVI", BIT(3)},
{"HDA_PGD4", BIT(2)},
{"HDA_PGD5", BIT(3)},
{"HDA_PGD6", BIT(4)},
{}
};
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.
*/
adl_pfear_map,
NULL
};
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},
{"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE},
{"XHCI", CNP_PMC_LTR_XHCI},
{"SOUTHPORT_F", ADL_PMC_LTR_SPF},
{"ME", CNP_PMC_LTR_ME},
/* EVA is Enterprise Value Add, doesn't really exist on PCH */
{"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", CNP_PMC_LTR_CAM},
{"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},
/*
* Check intel_pmc_core_ids[] users of cnp_reg_map for
* a list of core SoCs using this.
*/
{"WIGIG", ICL_PMC_LTR_WIGIG},
{"THC0", TGL_PMC_LTR_THC0},
{"THC1", TGL_PMC_LTR_THC1},
{"SOUTHPORT_G", CNP_PMC_LTR_RESERVED},
/* Below two cannot be used for LTR_IGNORE */
{"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT},
{"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT},
{}
};
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)},
{"CLKPART4_OFF_STS", BIT(3)},
{"CLKPART5_OFF_STS", BIT(4)},
{"CLKPART6_OFF_STS", BIT(5)},
{"CLKPART7_OFF_STS", BIT(6)},
{"CLKPART8_OFF_STS", BIT(7)},
{"PCIE0PLL_OFF_STS", BIT(10)},
{"PCIE1PLL_OFF_STS", BIT(11)},
{"PCIE2PLL_OFF_STS", BIT(12)},
{"PCIE3PLL_OFF_STS", BIT(13)},
{"PCIE4PLL_OFF_STS", BIT(14)},
{"PCIE5PLL_OFF_STS", BIT(15)},
{"PCIE6PLL_OFF_STS", BIT(16)},
{"USB2PLL_OFF_STS", BIT(18)},
{"OCPLL_OFF_STS", BIT(22)},
{"AUDIOPLL_OFF_STS", BIT(23)},
{"GBEPLL_OFF_STS", BIT(24)},
{"Fast_XTAL_Osc_OFF_STS", BIT(25)},
{"AC_Ring_Osc_OFF_STS", BIT(26)},
{"MC_Ring_Osc_OFF_STS", BIT(27)},
{"SATAPLL_OFF_STS", BIT(29)},
{"USB3PLL_OFF_STS", BIT(31)},
{}
};
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)},
{"XHCI_PGD0_PG_STS", BIT(3)},
{"SPA_PGD0_PG_STS", BIT(4)},
{"SPB_PGD0_PG_STS", BIT(5)},
{"SPC_PGD0_PG_STS", BIT(6)},
{"GBE_PGD0_PG_STS", BIT(7)},
{"SATA_PGD0_PG_STS", BIT(8)},
{"DSP_PGD0_PG_STS", BIT(9)},
{"DSP_PGD1_PG_STS", BIT(10)},
{"DSP_PGD2_PG_STS", BIT(11)},
{"DSP_PGD3_PG_STS", BIT(12)},
{"SPD_PGD0_PG_STS", BIT(13)},
{"LPSS_PGD0_PG_STS", BIT(14)},
{"SMB_PGD0_PG_STS", BIT(16)},
{"ISH_PGD0_PG_STS", BIT(17)},
{"NPK_PGD0_PG_STS", BIT(19)},
{"PECI_PGD0_PG_STS", BIT(21)},
{"XDCI_PGD0_PG_STS", BIT(25)},
{"EXI_PGD0_PG_STS", BIT(26)},
{"CSE_PGD0_PG_STS", BIT(27)},
{"KVMCC_PGD0_PG_STS", BIT(28)},
{"PMT_PGD0_PG_STS", BIT(29)},
{"CLINK_PGD0_PG_STS", BIT(30)},
{"PTIO_PGD0_PG_STS", BIT(31)},
{}
};
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)},
{"CSMEPSF_PGD0_PG_STS", BIT(7)},
{"CNVI_PGD0_PG_STS", BIT(19)},
{"DSP_PGD4_PG_STS", BIT(26)},
{"SPG_PGD0_PG_STS", BIT(27)},
{"SPE_PGD0_PG_STS", BIT(28)},
{}
};
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)},
{}
};
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)},
{"XHCI_D3_STS", BIT(5)},
{"SPA_D3_STS", BIT(12)},
{"SPB_D3_STS", BIT(13)},
{"SPC_D3_STS", BIT(14)},
{"SPD_D3_STS", BIT(15)},
{"SPE_D3_STS", BIT(16)},
{"DSP_D3_STS", BIT(19)},
{"SATA_D3_STS", BIT(20)},
{"DMI_D3_STS", BIT(22)},
{}
};
static const struct pmc_bit_map adl_d3_status_1_map[] = {
{"GBE_D3_STS", BIT(19)},
{"CNVI_D3_STS", BIT(27)},
{}
};
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)},
{"USBR0_D3_STS", BIT(6)},
{"SMT1_D3_STS", BIT(8)},
{"PTIO_D3_STS", BIT(16)},
{"PMT_D3_STS", BIT(17)},
{}
};
static const struct pmc_bit_map adl_d3_status_3_map[] = {
{"THC0_D3_STS", BIT(14)},
{"THC1_D3_STS", BIT(15)},
{}
};
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)},
{}
};
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)},
{"SMB_VNN_REQ_STS", BIT(25)},
{"CNVI_VNN_REQ_STS", BIT(27)},
{}
};
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)},
{"CLINK_VNN_REQ_STS", BIT(14)},
{"GPIOCOM4_VNN_REQ_STS", BIT(20)},
{"GPIOCOM3_VNN_REQ_STS", BIT(21)},
{"GPIOCOM2_VNN_REQ_STS", BIT(22)},
{"GPIOCOM1_VNN_REQ_STS", BIT(23)},
{"GPIOCOM0_VNN_REQ_STS", BIT(24)},
{}
};
static const struct pmc_bit_map adl_vnn_req_status_3_map[] = {
{"GPIOCOM5_VNN_REQ_STS", BIT(11)},
{}
};
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)},
{"CNVI_REQ_STS", BIT(6)},
{"ISH_REQ_STS", BIT(7)},
{"USB2_SUS_PG_Sys_REQ_STS", BIT(10)},
{"PCIe_Clk_REQ_STS", BIT(12)},
{"MPHY_Core_DL_REQ_STS", BIT(16)},
{"Break-even_En_REQ_STS", BIT(17)},
{"MPHY_SUS_REQ_STS", BIT(22)},
{"xDCI_attached_REQ_STS", BIT(24)},
{}
};
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,
adl_power_gating_status_2_map,
adl_d3_status_0_map,
adl_d3_status_1_map,
adl_d3_status_2_map,
adl_d3_status_3_map,
adl_vnn_req_status_0_map,
adl_vnn_req_status_1_map,
adl_vnn_req_status_2_map,
adl_vnn_req_status_3_map,
adl_vnn_misc_status_map,
tgl_signal_status_map,
NULL
};
static const struct pmc_reg_map adl_reg_map = {
.pfear_sts = ext_adl_pfear_map,
.slp_s0_offset = ADL_PMC_SLP_S0_RES_COUNTER_OFFSET,
.slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP,
.ltr_show_sts = adl_ltr_show_map,
.msr_sts = msr_map,
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
.regmap_length = CNP_PMC_MMIO_REG_LEN,
.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
.ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES,
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED,
.lpm_num_modes = ADL_LPM_NUM_MODES,
.lpm_num_maps = ADL_LPM_NUM_MAPS,
.lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2,
.etr3_offset = ETR3_OFFSET,
.lpm_sts_latch_en_offset = ADL_LPM_STATUS_LATCH_EN_OFFSET,
.lpm_priority_offset = ADL_LPM_PRI_OFFSET,
.lpm_en_offset = ADL_LPM_EN_OFFSET,
.lpm_residency_offset = ADL_LPM_RESIDENCY_OFFSET,
.lpm_sts = adl_lpm_maps,
.lpm_status_offset = ADL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET,
};
static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
{
return readl(pmcdev->regbase + reg_offset);
@ -1449,9 +1749,42 @@ static int pmc_core_pkgc_show(struct seq_file *s, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_pkgc);
static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev)
static bool pmc_core_pri_verify(u32 lpm_pri, u8 *mode_order)
{
u8 lpm_priority[LPM_MAX_NUM_MODES];
int i, j;
if (!lpm_pri)
return false;
/*
* Each byte contains the priority level for 2 modes (7:4 and 3:0).
* In a 32 bit register this allows for describing 8 modes. Store the
* levels and look for values out of range.
*/
for (i = 0; i < 8; i++) {
int level = lpm_pri & GENMASK(3, 0);
if (level >= LPM_MAX_NUM_MODES)
return false;
mode_order[i] = level;
lpm_pri >>= 4;
}
/* Check that we have unique values */
for (i = 0; i < LPM_MAX_NUM_MODES - 1; i++)
for (j = i + 1; j < LPM_MAX_NUM_MODES; j++)
if (mode_order[i] == mode_order[j])
return false;
return true;
}
static void pmc_core_get_low_power_modes(struct platform_device *pdev)
{
struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
u8 pri_order[LPM_MAX_NUM_MODES] = LPM_DEFAULT_PRI;
u8 mode_order[LPM_MAX_NUM_MODES];
u32 lpm_pri;
u32 lpm_en;
int mode, i, p;
@ -1462,24 +1795,28 @@ static void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev)
lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset);
pmcdev->num_lpm_modes = hweight32(lpm_en);
/* Each byte contains information for 2 modes (7:4 and 3:0) */
for (mode = 0; mode < LPM_MAX_NUM_MODES; mode += 2) {
u8 priority = pmc_core_reg_read_byte(pmcdev,
pmcdev->map->lpm_priority_offset + (mode / 2));
int pri0 = GENMASK(3, 0) & priority;
int pri1 = (GENMASK(7, 4) & priority) >> 4;
/* Read 32 bit LPM_PRI register */
lpm_pri = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_priority_offset);
lpm_priority[pri0] = mode;
lpm_priority[pri1] = mode + 1;
}
/*
* Loop though all modes from lowest to highest priority,
* If lpm_pri value passes verification, then override the default
* modes here. Otherwise stick with the default.
*/
if (pmc_core_pri_verify(lpm_pri, mode_order))
/* Get list of modes in priority order */
for (mode = 0; mode < LPM_MAX_NUM_MODES; mode++)
pri_order[mode_order[mode]] = mode;
else
dev_warn(&pdev->dev, "Assuming a default substate order for this platform\n");
/*
* Loop through all modes from lowest to highest priority,
* and capture all enabled modes in order
*/
i = 0;
for (p = LPM_MAX_NUM_MODES - 1; p >= 0; p--) {
int mode = lpm_priority[p];
int mode = pri_order[p];
if (!(BIT(mode) & lpm_en))
continue;
@ -1574,6 +1911,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &icl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_reg_map),
{}
};
@ -1675,17 +2013,17 @@ static int pmc_core_probe(struct platform_device *pdev)
mutex_init(&pmcdev->lock);
pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev);
pmc_core_get_low_power_modes(pmcdev);
pmc_core_get_low_power_modes(pdev);
pmc_core_do_dmi_quirks(pmcdev);
if (pmcdev->map == &tgl_reg_map)
pmc_core_get_tgl_lpm_reqs(pdev);
/*
* On TGL, due to a hardware limitation, the GBE LTR blocks PC10 when
* a cable is attached. Tell the PMC to ignore it.
* On TGL and ADL, due to a hardware limitation, the GBE LTR blocks PC10
* when a cable is attached. Tell the PMC to ignore it.
*/
if (pmcdev->map == &tgl_reg_map) {
if (pmcdev->map == &tgl_reg_map || pmcdev->map == &adl_reg_map) {
dev_dbg(&pdev->dev, "ignoring GBE LTR\n");
pmc_core_send_ltr_ignore(pmcdev, 3);
}

View File

@ -188,6 +188,8 @@ enum ppfear_regs {
#define ICL_PMC_SLP_S0_RES_COUNTER_STEP 0x64
#define LPM_MAX_NUM_MODES 8
#define LPM_DEFAULT_PRI { 7, 6, 2, 5, 4, 1, 3, 0 }
#define GET_X2_COUNTER(v) ((v) >> 1)
#define LPM_STS_LATCH_MODE BIT(31)
@ -197,6 +199,10 @@ enum ppfear_regs {
#define TGL_NUM_IP_IGN_ALLOWED 23
#define TGL_PMC_LPM_RES_COUNTER_STEP_X2 61 /* 30.5us * 2 */
#define ADL_PMC_LTR_SPF 0x1C00
#define ADL_NUM_IP_IGN_ALLOWED 23
#define ADL_PMC_SLP_S0_RES_COUNTER_OFFSET 0x1098
/*
* Tigerlake Power Management Controller register offsets
*/
@ -218,6 +224,18 @@ enum ppfear_regs {
/* Extended Test Mode Register LPM bits (TGL and later */
#define ETR3_CLEAR_LPM_EVENTS BIT(28)
/* Alder Lake Power Management Controller register offsets */
#define ADL_LPM_EN_OFFSET 0x179C
#define ADL_LPM_RESIDENCY_OFFSET 0x17A4
#define ADL_LPM_NUM_MODES 2
#define ADL_LPM_NUM_MAPS 14
/* Alder Lake Low Power Mode debug registers */
#define ADL_LPM_STATUS_OFFSET 0x170C
#define ADL_LPM_PRI_OFFSET 0x17A0
#define ADL_LPM_STATUS_LATCH_EN_OFFSET 0x1704
#define ADL_LPM_LIVE_STATUS_OFFSET 0x1764
const char *pmc_lpm_modes[] = {
"S0i2.0",
"S0i2.1",
@ -277,6 +295,7 @@ struct pmc_reg_map {
const u32 pm_vric1_offset;
/* Low Power Mode registers */
const int lpm_num_maps;
const int lpm_num_modes;
const int lpm_res_counter_step_x2;
const u32 lpm_sts_latch_en_offset;
const u32 lpm_en_offset;

View File

@ -0,0 +1,40 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Intel Platform Monitoring Technology drivers
#
config INTEL_PMT_CLASS
tristate
help
The Intel Platform Monitoring Technology (PMT) class driver provides
the basic sysfs interface and file hierarchy used by PMT devices.
For more information, see:
<file:Documentation/ABI/testing/sysfs-class-intel_pmt>
To compile this driver as a module, choose M here: the module
will be called intel_pmt_class.
config INTEL_PMT_TELEMETRY
tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver"
depends on MFD_INTEL_PMT
select INTEL_PMT_CLASS
help
The Intel Platform Monitory Technology (PMT) Telemetry driver provides
access to hardware telemetry metrics on devices that support the
feature.
To compile this driver as a module, choose M here: the module
will be called intel_pmt_telemetry.
config INTEL_PMT_CRASHLOG
tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver"
depends on MFD_INTEL_PMT
select INTEL_PMT_CLASS
help
The Intel Platform Monitoring Technology (PMT) crashlog driver provides
access to hardware crashlog capabilities on devices that support the
feature.
To compile this driver as a module, choose M here: the module
will be called intel_pmt_crashlog.

View File

@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for linux/drivers/platform/x86/intel/pmt
# Intel Platform Monitoring Technology Drivers
#
obj-$(CONFIG_INTEL_PMT_CLASS) += pmt_class.o
pmt_class-y := class.o
obj-$(CONFIG_INTEL_PMT_TELEMETRY) += pmt_telemetry.o
pmt_telemetry-y := telemetry.o
obj-$(CONFIG_INTEL_PMT_CRASHLOG) += pmt_crashlog.o
pmt_crashlog-y := crashlog.o

View File

@ -13,7 +13,7 @@
#include <linux/mm.h>
#include <linux/pci.h>
#include "intel_pmt_class.h"
#include "class.h"
#define PMT_XA_START 0
#define PMT_XA_MAX INT_MAX

View File

@ -15,7 +15,7 @@
#include <linux/uaccess.h>
#include <linux/overflow.h>
#include "intel_pmt_class.h"
#include "class.h"
#define DRV_NAME "pmt_crashlog"

View File

@ -15,7 +15,7 @@
#include <linux/uaccess.h>
#include <linux/overflow.h>
#include "intel_pmt_class.h"
#include "class.h"
#define TELEM_DEV_NAME "pmt_telemetry"
@ -61,6 +61,14 @@ static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
/* Size is measured in DWORDS, but accessor returns bytes */
header->size = TELEM_SIZE(readl(disc_table));
/*
* Some devices may expose non-functioning entries that are
* reserved for future use. They have zero size. Do not fail
* probe for these. Just ignore them.
*/
if (header->size == 0)
return 1;
return 0;
}

View File

@ -265,9 +265,9 @@ static int isst_if_get_platform_info(void __user *argp)
{
struct isst_if_platform_info info;
info.api_version = ISST_IF_API_VERSION,
info.driver_version = ISST_IF_DRIVER_VERSION,
info.max_cmds_per_ioctl = ISST_IF_CMD_LIMIT,
info.api_version = ISST_IF_API_VERSION;
info.driver_version = ISST_IF_DRIVER_VERSION;
info.max_cmds_per_ioctl = ISST_IF_CMD_LIMIT;
info.mbox_supported = punit_callbacks[ISST_IF_DEV_MBOX].registered;
info.mmio_supported = punit_callbacks[ISST_IF_DEV_MMIO].registered;
@ -379,6 +379,8 @@ static int isst_if_cpu_online(unsigned int cpu)
u64 data;
int ret;
isst_cpu_info[cpu].numa_node = cpu_to_node(cpu);
ret = rdmsrl_safe(MSR_CPU_BUS_NUMBER, &data);
if (ret) {
/* This is not a fatal error on MSR mailbox only I/F */
@ -397,7 +399,6 @@ static int isst_if_cpu_online(unsigned int cpu)
return ret;
}
isst_cpu_info[cpu].punit_cpu_id = data;
isst_cpu_info[cpu].numa_node = cpu_to_node(cpu);
isst_restore_msr_local(cpu);

View File

@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Intel x86 Platform Specific Drivers
#
config INTEL_TELEMETRY
tristate "Intel SoC Telemetry driver"
depends on X86_64
depends on MFD_INTEL_PMC_BXT
depends on INTEL_PUNIT_IPC
help
This driver provides interfaces to configure and use
telemetry for Intel SoC from Apollo Lake onwards.
It is also used to get various SoC events and parameters
directly via debugfs files. Various tools may use
this interface for SoC state monitoring.

View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Intel x86 Platform Specific Drivers
#
intel_telemetry_core-y := core.o
obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o
intel_telemetry_pltdrv-y := pltdrv.o
obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_pltdrv.o
intel_telemetry_debugfs-y := debugfs.o
obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_debugfs.o

View File

@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
#include "dual_accel_detect.h"
#include "../dual_accel_detect.h"
/* Returned when NOT in tablet mode on some HP Stream x360 11 models */
#define VGBS_TABLET_MODE_FLAG_ALT 0x10

View File

@ -0,0 +1,31 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Intel x86 Platform Specific Drivers
#
config INTEL_WMI
bool
config INTEL_WMI_SBL_FW_UPDATE
tristate "Intel WMI Slim Bootloader firmware update signaling driver"
depends on ACPI_WMI
select INTEL_WMI
help
Say Y here if you want to be able to use the WMI interface to signal
Slim Bootloader to trigger update on next reboot.
To compile this driver as a module, choose M here: the module will
be called intel-wmi-sbl-fw-update.
config INTEL_WMI_THUNDERBOLT
tristate "Intel WMI thunderbolt force power driver"
depends on ACPI_WMI
select INTEL_WMI
help
Say Y here if you want to be able to use the WMI interface on select
systems to force the power control of Intel Thunderbolt controllers.
This is useful for updating the firmware when devices are not plugged
into the controller.
To compile this driver as a module, choose M here: the module will
be called intel-wmi-thunderbolt.

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Intel x86 Platform Specific Drivers
#
intel-wmi-sbl-fw-update-y := sbl-fw-update.o
obj-$(CONFIG_INTEL_WMI_SBL_FW_UPDATE) += intel-wmi-sbl-fw-update.o
intel-wmi-thunderbolt-y := thunderbolt.o
obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o

View File

@ -457,7 +457,7 @@ int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd,
EXPORT_SYMBOL(intel_scu_ipc_dev_simple_command);
/**
* intel_scu_ipc_command_with_size() - Command with data
* intel_scu_ipc_dev_command_with_size() - Command with data
* @scu: Optional SCU IPC instance
* @cmd: Command
* @sub: Sub type

View File

@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/kernel.h>
@ -16,11 +17,12 @@
#include <linux/platform_device.h>
#include <linux/types.h>
#define LED_DEVICE(_name, max) struct led_classdev _name = { \
#define LED_DEVICE(_name, max, flag) struct led_classdev _name = { \
.name = __stringify(_name), \
.max_brightness = max, \
.brightness_set = _name##_set, \
.brightness_get = _name##_get, \
.flags = flag, \
}
MODULE_AUTHOR("Matan Ziv-Av");
@ -69,9 +71,13 @@ static u32 inited;
#define INIT_INPUT_ACPI 0x04
#define INIT_SPARSE_KEYMAP 0x80
static int battery_limit_use_wmbb;
static struct led_classdev kbd_backlight;
static enum led_brightness get_kbd_backlight_level(void);
static const struct key_entry wmi_keymap[] = {
{KE_KEY, 0x70, {KEY_F15} }, /* LG control panel (F1) */
{KE_KEY, 0x74, {KEY_F13} }, /* Touchpad toggle (F5) */
{KE_KEY, 0x74, {KEY_F21} }, /* Touchpad toggle (F5) */
{KE_KEY, 0xf020000, {KEY_F14} }, /* Read mode (F9) */
{KE_KEY, 0x10000000, {KEY_F16} },/* Keyboard backlight (F8) - pressing
* this key both sends an event and
@ -214,10 +220,16 @@ static void wmi_notify(u32 value, void *context)
int eventcode = obj->integer.value;
struct key_entry *key;
key =
sparse_keymap_entry_from_scancode(wmi_input_dev, eventcode);
if (key && key->type == KE_KEY)
sparse_keymap_report_entry(wmi_input_dev, key, 1, true);
if (eventcode == 0x10000000) {
led_classdev_notify_brightness_hw_changed(
&kbd_backlight, get_kbd_backlight_level());
} else {
key = sparse_keymap_entry_from_scancode(
wmi_input_dev, eventcode);
if (key && key->type == KE_KEY)
sparse_keymap_report_entry(wmi_input_dev,
key, 1, true);
}
}
pr_debug("Type: %i Eventcode: 0x%llx\n", obj->type,
@ -461,7 +473,10 @@ static ssize_t battery_care_limit_store(struct device *dev,
if (value == 100 || value == 80) {
union acpi_object *r;
r = lg_wmab(WM_BATT_LIMIT, WM_SET, value);
if (battery_limit_use_wmbb)
r = lg_wmbb(WMBB_BATT_LIMIT, WM_SET, value);
else
r = lg_wmab(WM_BATT_LIMIT, WM_SET, value);
if (!r)
return -EIO;
@ -479,16 +494,29 @@ static ssize_t battery_care_limit_show(struct device *dev,
unsigned int status;
union acpi_object *r;
r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0);
if (!r)
return -EIO;
if (battery_limit_use_wmbb) {
r = lg_wmbb(WMBB_BATT_LIMIT, WM_GET, 0);
if (!r)
return -EIO;
if (r->type != ACPI_TYPE_INTEGER) {
kfree(r);
return -EIO;
if (r->type != ACPI_TYPE_BUFFER) {
kfree(r);
return -EIO;
}
status = r->buffer.pointer[0x10];
} else {
r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0);
if (!r)
return -EIO;
if (r->type != ACPI_TYPE_INTEGER) {
kfree(r);
return -EIO;
}
status = r->integer.value;
}
status = r->integer.value;
kfree(r);
if (status != 80 && status != 100)
status = 0;
@ -529,7 +557,7 @@ static enum led_brightness tpad_led_get(struct led_classdev *cdev)
return ggov(GOV_TLED) > 0 ? LED_ON : LED_OFF;
}
static LED_DEVICE(tpad_led, 1);
static LED_DEVICE(tpad_led, 1, 0);
static void kbd_backlight_set(struct led_classdev *cdev,
enum led_brightness brightness)
@ -546,7 +574,7 @@ static void kbd_backlight_set(struct led_classdev *cdev,
kfree(r);
}
static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
static enum led_brightness get_kbd_backlight_level(void)
{
union acpi_object *r;
int val;
@ -577,7 +605,12 @@ static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
return val;
}
static LED_DEVICE(kbd_backlight, 255);
static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
{
return get_kbd_backlight_level();
}
static LED_DEVICE(kbd_backlight, 255, LED_BRIGHT_HW_CHANGED);
static void wmi_input_destroy(void)
{
@ -602,6 +635,8 @@ static struct platform_driver pf_driver = {
static int acpi_add(struct acpi_device *device)
{
int ret;
const char *product;
int year = 2017;
if (pf_device)
return 0;
@ -619,6 +654,42 @@ static int acpi_add(struct acpi_device *device)
pr_err("unable to register platform device\n");
goto out_platform_registered;
}
product = dmi_get_system_info(DMI_PRODUCT_NAME);
if (strlen(product) > 4)
switch (product[4]) {
case '5':
case '6':
year = 2016;
break;
case '7':
year = 2017;
break;
case '8':
year = 2018;
break;
case '9':
year = 2019;
break;
case '0':
if (strlen(product) > 5)
switch (product[5]) {
case 'N':
year = 2020;
break;
case 'P':
year = 2021;
break;
default:
year = 2022;
}
break;
default:
year = 2019;
}
pr_info("product: %s year: %d\n", product, year);
if (year >= 2019)
battery_limit_use_wmbb = 1;
ret = sysfs_create_group(&pf_device->dev.kobj, &dev_attribute_group);
if (ret)

View File

@ -0,0 +1,230 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Cisco Meraki MX100 (Tinkerbell) board platform driver
*
* Based off of arch/x86/platform/meraki/tink.c from the
* Meraki GPL release meraki-firmware-sources-r23-20150601
*
* Format inspired by platform/x86/pcengines-apuv2.c
*
* Copyright (C) 2021 Chris Blake <chrisrblake93@gmail.com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/dmi.h>
#include <linux/err.h>
#include <linux/gpio_keys.h>
#include <linux/gpio/machine.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#define TINK_GPIO_DRIVER_NAME "gpio_ich"
/* LEDs */
static const struct gpio_led tink_leds[] = {
{
.name = "mx100:green:internet",
.default_trigger = "default-on",
},
{
.name = "mx100:green:lan2",
},
{
.name = "mx100:green:lan3",
},
{
.name = "mx100:green:lan4",
},
{
.name = "mx100:green:lan5",
},
{
.name = "mx100:green:lan6",
},
{
.name = "mx100:green:lan7",
},
{
.name = "mx100:green:lan8",
},
{
.name = "mx100:green:lan9",
},
{
.name = "mx100:green:lan10",
},
{
.name = "mx100:green:lan11",
},
{
.name = "mx100:green:ha",
},
{
.name = "mx100:orange:ha",
},
{
.name = "mx100:green:usb",
},
{
.name = "mx100:orange:usb",
},
};
static const struct gpio_led_platform_data tink_leds_pdata = {
.num_leds = ARRAY_SIZE(tink_leds),
.leds = tink_leds,
};
static struct gpiod_lookup_table tink_leds_table = {
.dev_id = "leds-gpio",
.table = {
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 11,
NULL, 0, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 18,
NULL, 1, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 20,
NULL, 2, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 22,
NULL, 3, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 23,
NULL, 4, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 32,
NULL, 5, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 34,
NULL, 6, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 35,
NULL, 7, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 36,
NULL, 8, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 37,
NULL, 9, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 48,
NULL, 10, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 16,
NULL, 11, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 7,
NULL, 12, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 21,
NULL, 13, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 19,
NULL, 14, GPIO_ACTIVE_LOW),
{} /* Terminating entry */
}
};
/* Reset Button */
static struct gpio_keys_button tink_buttons[] = {
{
.desc = "Reset",
.type = EV_KEY,
.code = KEY_RESTART,
.active_low = 1,
.debounce_interval = 100,
},
};
static const struct gpio_keys_platform_data tink_buttons_pdata = {
.buttons = tink_buttons,
.nbuttons = ARRAY_SIZE(tink_buttons),
.poll_interval = 20,
.rep = 0,
.name = "mx100-keys",
};
static struct gpiod_lookup_table tink_keys_table = {
.dev_id = "gpio-keys-polled",
.table = {
GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 60,
NULL, 0, GPIO_ACTIVE_LOW),
{} /* Terminating entry */
}
};
/* Board setup */
static const struct dmi_system_id tink_systems[] __initconst = {
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Cisco"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MX100-HW"),
},
},
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE(dmi, tink_systems);
static struct platform_device *tink_leds_pdev;
static struct platform_device *tink_keys_pdev;
static struct platform_device * __init tink_create_dev(
const char *name, const void *pdata, size_t sz)
{
struct platform_device *pdev;
pdev = platform_device_register_data(NULL,
name, PLATFORM_DEVID_NONE, pdata, sz);
if (IS_ERR(pdev))
pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev));
return pdev;
}
static int __init tink_board_init(void)
{
int ret;
if (!dmi_first_match(tink_systems))
return -ENODEV;
/*
* We need to make sure that GPIO60 isn't set to native mode as is default since it's our
* Reset Button. To do this, write to GPIO_USE_SEL2 to have GPIO60 set to GPIO mode.
* This is documented on page 1609 of the PCH datasheet, order number 327879-005US
*/
outl(inl(0x530) | BIT(28), 0x530);
gpiod_add_lookup_table(&tink_leds_table);
gpiod_add_lookup_table(&tink_keys_table);
tink_leds_pdev = tink_create_dev("leds-gpio",
&tink_leds_pdata, sizeof(tink_leds_pdata));
if (IS_ERR(tink_leds_pdev)) {
ret = PTR_ERR(tink_leds_pdev);
goto err;
}
tink_keys_pdev = tink_create_dev("gpio-keys-polled",
&tink_buttons_pdata, sizeof(tink_buttons_pdata));
if (IS_ERR(tink_keys_pdev)) {
ret = PTR_ERR(tink_keys_pdev);
platform_device_unregister(tink_leds_pdev);
goto err;
}
return 0;
err:
gpiod_remove_lookup_table(&tink_keys_table);
gpiod_remove_lookup_table(&tink_leds_table);
return ret;
}
module_init(tink_board_init);
static void __exit tink_board_exit(void)
{
platform_device_unregister(tink_keys_pdev);
platform_device_unregister(tink_leds_pdev);
gpiod_remove_lookup_table(&tink_keys_table);
gpiod_remove_lookup_table(&tink_leds_table);
}
module_exit(tink_board_exit);
MODULE_AUTHOR("Chris Blake <chrisrblake93@gmail.com>");
MODULE_DESCRIPTION("Cisco Meraki MX100 Platform Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:meraki-mx100");

View File

@ -20,6 +20,10 @@
#include "firmware_attributes_class.h"
#include "think-lmi.h"
static bool debug_support;
module_param(debug_support, bool, 0444);
MODULE_PARM_DESC(debug_support, "Enable debug command support");
/*
* Name:
* Lenovo_BiosSetting
@ -116,6 +120,14 @@
*/
#define LENOVO_GET_BIOS_SELECTIONS_GUID "7364651A-132F-4FE7-ADAA-40C6C7EE2E3B"
/*
* Name:
* Lenovo_DebugCmdGUID
* Description
* Debug entry GUID method for entering debug commands to the BIOS
*/
#define LENOVO_DEBUG_CMD_GUID "7FF47003-3B6C-4E5E-A227-E979824A85D1"
#define TLMI_POP_PWD (1 << 0)
#define TLMI_PAP_PWD (1 << 1)
#define to_tlmi_pwd_setting(kobj) container_of(kobj, struct tlmi_pwd_setting, kobj)
@ -660,6 +672,64 @@ static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *
static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
/* ---- Debug interface--------------------------------------------------------- */
static ssize_t debug_cmd_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
char *set_str = NULL, *new_setting = NULL;
char *auth_str = NULL;
char *p;
int ret;
if (!tlmi_priv.can_debug_cmd)
return -EOPNOTSUPP;
new_setting = kstrdup(buf, GFP_KERNEL);
if (!new_setting)
return -ENOMEM;
/* Strip out CR if one is present */
p = strchrnul(new_setting, '\n');
*p = '\0';
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
tlmi_priv.pwd_admin->password,
encoding_options[tlmi_priv.pwd_admin->encoding],
tlmi_priv.pwd_admin->kbdlang);
if (!auth_str) {
ret = -ENOMEM;
goto out;
}
}
if (auth_str)
set_str = kasprintf(GFP_KERNEL, "%s,%s", new_setting, auth_str);
else
set_str = kasprintf(GFP_KERNEL, "%s;", new_setting);
if (!set_str) {
ret = -ENOMEM;
goto out;
}
ret = tlmi_simple_call(LENOVO_DEBUG_CMD_GUID, set_str);
if (ret)
goto out;
if (!ret && !tlmi_priv.pending_changes) {
tlmi_priv.pending_changes = true;
/* let userland know it may need to check reboot pending again */
kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
}
out:
kfree(auth_str);
kfree(set_str);
kfree(new_setting);
return ret ?: count;
}
static struct kobj_attribute debug_cmd = __ATTR_WO(debug_cmd);
/* ---- Initialisation --------------------------------------------------------- */
static void tlmi_release_attr(void)
{
@ -673,6 +743,8 @@ static void tlmi_release_attr(void)
}
}
sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr);
if (tlmi_priv.can_debug_cmd && debug_support)
sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
kset_unregister(tlmi_priv.attribute_kset);
/* Authentication structures */
@ -737,6 +809,11 @@ static int tlmi_sysfs_init(void)
if (ret)
goto fail_create_attr;
if (tlmi_priv.can_debug_cmd && debug_support) {
ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
if (ret)
goto fail_create_attr;
}
/* Create authentication entries */
tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL,
&tlmi_priv.class_dev->kobj);
@ -793,6 +870,9 @@ static int tlmi_analyze(void)
if (wmi_has_guid(LENOVO_BIOS_PASSWORD_SETTINGS_GUID))
tlmi_priv.can_get_password_settings = true;
if (wmi_has_guid(LENOVO_DEBUG_CMD_GUID))
tlmi_priv.can_debug_cmd = true;
/*
* Try to find the number of valid settings of this machine
* and use it to create sysfs attributes.

View File

@ -61,6 +61,7 @@ struct think_lmi {
bool can_set_bios_password;
bool can_get_password_settings;
bool pending_changes;
bool can_debug_cmd;
struct tlmi_attr_setting *setting[TLMI_SETTINGS_COUNT];
struct device *class_dev;

View File

@ -90,3 +90,12 @@ config INTEL_TCC_COOLING
Note that, on different platforms, the behavior might be different
on how fast the setting takes effect, and how much the CPU frequency
is reduced.
config INTEL_MENLOW
tristate "Thermal Management driver for Intel menlow platform"
depends on ACPI_THERMAL
help
ACPI thermal management enhancement driver on
Intel Menlow platform.
If unsure, say N.

View File

@ -12,3 +12,4 @@ obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-$(CONFIG_INTEL_TCC_COOLING) += intel_tcc_cooling.o
obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o

View File

@ -1010,6 +1010,7 @@ struct acpi_resource_i2c_serialbus;
#if IS_ENABLED(CONFIG_ACPI)
bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
struct acpi_resource_i2c_serialbus **i2c);
int i2c_acpi_client_count(struct acpi_device *adev);
u32 i2c_acpi_find_bus_speed(struct device *dev);
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
struct i2c_board_info *info);
@ -1020,6 +1021,10 @@ static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
{
return false;
}
static inline int i2c_acpi_client_count(struct acpi_device *adev)
{
return 0;
}
static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
{
return 0;

View File

@ -61,6 +61,7 @@
#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075
/* Misc */
#define ASUS_WMI_DEVID_PANEL_OD 0x00050019
#define ASUS_WMI_DEVID_CAMERA 0x00060013
#define ASUS_WMI_DEVID_LID_FLIP 0x00060062
@ -89,6 +90,12 @@
/* Keyboard dock */
#define ASUS_WMI_DEVID_KBD_DOCK 0x00120063
/* dgpu on/off */
#define ASUS_WMI_DEVID_EGPU 0x00090019
/* dgpu on/off */
#define ASUS_WMI_DEVID_DGPU 0x00090020
/* DSTS masks */
#define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
#define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002