Commit 14646776 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'platform-drivers-x86-v5.18-1' of...

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

Pull x86 platform driver updates from Hans de Goede:
  "New drivers:
    - AMD Host System Management Port (HSMP)
    - Intel Software Defined Silicon

  Removed drivers (functionality folded into other drivers):
    - intel_cht_int33fe_microb
    - surface3_button

  amd-pmc:
    - s2idle bug-fixes
    - Support for AMD Spill to DRAM STB feature

  hp-wmi:
    - Fix SW_TABLET_MODE detection method (and other fixes)
    - Support omen thermal profile policy v1

  serial-multi-instantiate:
    - Add SPI device support
    - Add support for CS35L41 amplifiers used in new laptops

  think-lmi:
    - syfs-class-firmware-attributes Certificate authentication support

  thinkpad_acpi:
    - Fixes + quirks
    - Add platform_profile support on AMD based ThinkPads

  x86-android-tablets:
    - Improve Asus ME176C / TF103C support
    - Support Nextbook Ares 8, Lenovo Tab 2 830 and 1050 tablets

  Lots of various other small fixes and hardware-id additions"

* tag 'platform-drivers-x86-v5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (60 commits)
  platform/x86: think-lmi: Certificate authentication support
  Documentation: syfs-class-firmware-attributes: Lenovo Certificate support
  platform/x86: amd-pmc: Only report STB errors when STB enabled
  platform/x86: amd-pmc: Drop CPU QoS workaround
  platform/x86: amd-pmc: Output error codes in messages
  platform/x86: amd-pmc: Move to later in the suspend process
  ACPI / x86: Add support for LPS0 callback handler
  platform/x86: thinkpad_acpi: consistently check fan_get_status return.
  platform/x86: hp-wmi: support omen thermal profile policy v1
  platform/x86: hp-wmi: Changing bios_args.data to be dynamically allocated
  platform/x86: hp-wmi: Fix 0x05 error code reported by several WMI calls
  platform/x86: hp-wmi: Fix SW_TABLET_MODE detection method
  platform/x86: hp-wmi: Fix hp_wmi_read_int() reporting error (0x05)
  platform/x86: amd-pmc: Validate entry into the deepest state on resume
  platform/x86: thinkpad_acpi: Don't use test_bit on an integer
  platform/x86: thinkpad_acpi: Fix compiler warning about uninitialized err variable
  platform/x86: thinkpad_acpi: clean up dytc profile convert
  platform/x86: x86-android-tablets: Depend on EFI and SPI
  platform/x86: amd-pmc: uninitialized variable in amd_pmc_s2d_init()
  platform/x86: intel-uncore-freq: fix uncore_freq_common_init() error codes
  ...
parents 50560ce6 b49f72e7
...@@ -246,6 +246,51 @@ Description: ...@@ -246,6 +246,51 @@ Description:
that is being referenced (e.g hdd0, hdd1 etc) that is being referenced (e.g hdd0, hdd1 etc)
This attribute defaults to device 0. This attribute defaults to device 0.
certificate:
signature:
save_signature:
These attributes are used for certificate based authentication. This is
used in conjunction with a signing server as an alternative to password
based authentication.
The user writes to the attribute(s) with a BASE64 encoded string obtained
from the signing server.
The attributes can be displayed to check the stored value.
Some usage examples:
Installing a certificate to enable feature:
echo <supervisor password > authentication/Admin/current_password
echo <signed certificate> > authentication/Admin/certificate
Updating the installed certificate:
echo <signature> > authentication/Admin/signature
echo <signed certificate> > authentication/Admin/certificate
Removing the installed certificate:
echo <signature> > authentication/Admin/signature
echo '' > authentication/Admin/certificate
Changing a BIOS setting:
echo <signature> > authentication/Admin/signature
echo <save signature> > authentication/Admin/save_signature
echo Enable > attribute/PasswordBeep/current_value
You cannot enable certificate authentication if a supervisor password
has not been set.
Clearing the certificate results in no bios-admin authentication method
being configured allowing anyone to make changes.
After any of these operations the system must reboot for the changes to
take effect.
certificate_thumbprint:
Read only attribute used to display the MD5, SHA1 and SHA256 thumbprints
for the certificate installed in the BIOS.
certificate_to_password:
Write only attribute used to switch from certificate based authentication
back to password based.
Usage:
echo <signature> > authentication/Admin/signature
echo <password> > authentication/Admin/certificate_to_password
What: /sys/class/firmware-attributes/*/attributes/pending_reboot What: /sys/class/firmware-attributes/*/attributes/pending_reboot
......
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X
Date: Feb 2022
KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
This directory contains interface files for accessing Intel
Software Defined Silicon (SDSi) features on a CPU. X
represents the socket instance (though not the socket ID).
The socket ID is determined by reading the registers file
and decoding it per the specification.
Some files communicate with SDSi hardware through a mailbox.
Should the operation fail, one of the following error codes
may be returned:
Error Code Cause
---------- -----
EIO General mailbox failure. Log may indicate cause.
EBUSY Mailbox is owned by another agent.
EPERM SDSI capability is not enabled in hardware.
EPROTO Failure in mailbox protocol detected by driver.
See log for details.
EOVERFLOW For provision commands, the size of the data
exceeds what may be written.
ESPIPE Seeking is not allowed.
ETIMEDOUT Failure to complete mailbox transaction in time.
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/guid
Date: Feb 2022
KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
(RO) The GUID for the registers file. The GUID identifies
the layout of the registers file in this directory.
Information about the register layouts for a particular GUID
is available at http://github.com/intel/intel-sdsi
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/registers
Date: Feb 2022
KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
(RO) Contains information needed by applications to provision
a CPU and monitor status information. The layout of this file
is determined by the GUID in this directory. Information about
the layout for a particular GUID is available at
http://github.com/intel/intel-sdsi
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/provision_akc
Date: Feb 2022
KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
(WO) Used to write an Authentication Key Certificate (AKC) to
the SDSi NVRAM for the CPU. The AKC is used to authenticate a
Capability Activation Payload. Mailbox command.
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/provision_cap
Date: Feb 2022
KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
(WO) Used to write a Capability Activation Payload (CAP) to the
SDSi NVRAM for the CPU. CAPs are used to activate a given CPU
feature. A CAP is validated by SDSi hardware using a previously
provisioned AKC file. Upon successful authentication, the CPU
configuration is updated. A cold reboot is required to fully
activate the feature. Mailbox command.
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/state_certificate
Date: Feb 2022
KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
(RO) Used to read back the current State Certificate for the CPU
from SDSi hardware. The State Certificate contains information
about the current licenses on the CPU. Mailbox command.
...@@ -17,6 +17,7 @@ Date: October 2018 ...@@ -17,6 +17,7 @@ Date: October 2018
KernelVersion: 4.20 KernelVersion: 4.20
Contact: "Matan Ziv-Av <matan@svgalib.org> Contact: "Matan Ziv-Av <matan@svgalib.org>
Description: Description:
Deprecated use /sys/class/power_supply/CMB0/charge_control_end_threshold
Maximal battery charge level. Accepted values are 80 or 100. Maximal battery charge level. Accepted values are 80 or 100.
What: /sys/devices/platform/lg-laptop/fan_mode What: /sys/devices/platform/lg-laptop/fan_mode
......
...@@ -38,7 +38,7 @@ FN lock. ...@@ -38,7 +38,7 @@ FN lock.
Battery care limit Battery care limit
------------------ ------------------
Writing 80/100 to /sys/devices/platform/lg-laptop/battery_care_limit Writing 80/100 to /sys/class/power_supply/CMB0/charge_control_end_threshold
sets the maximum capacity to charge the battery. Limiting the charge sets the maximum capacity to charge the battery. Limiting the charge
reduces battery capacity loss over time. reduces battery capacity loss over time.
......
...@@ -375,6 +375,8 @@ Code Seq# Include File Comments ...@@ -375,6 +375,8 @@ Code Seq# Include File Comments
<mailto:thomas@winischhofer.net> <mailto:thomas@winischhofer.net>
0xF6 all LTTng Linux Trace Toolkit Next Generation 0xF6 all LTTng Linux Trace Toolkit Next Generation
<mailto:mathieu.desnoyers@efficios.com> <mailto:mathieu.desnoyers@efficios.com>
0xF8 all arch/x86/include/uapi/asm/amd_hsmp.h AMD HSMP EPYC system management interface driver
<mailto:nchatrad@amd.com>
0xFD all linux/dm-ioctl.h 0xFD all linux/dm-ioctl.h
0xFE all linux/isst_if.h 0xFE all linux/isst_if.h
==== ===== ======================================================= ================================================================ ==== ===== ======================================================= ================================================================
.. SPDX-License-Identifier: GPL-2.0
============================================
AMD HSMP interface
============================================
Newer Fam19h EPYC server line of processors from AMD support system
management functionality via HSMP (Host System Management Port).
The Host System Management Port (HSMP) is an interface to provide
OS-level software with access to system management functions via a
set of mailbox registers.
More details on the interface can be found in chapter
"7 Host System Management Port (HSMP)" of the family/model PPR
Eg: https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
HSMP interface is supported on EPYC server CPU models only.
HSMP device
============================================
amd_hsmp driver under the drivers/platforms/x86/ creates miscdevice
/dev/hsmp to let user space programs run hsmp mailbox commands.
$ ls -al /dev/hsmp
crw-r--r-- 1 root root 10, 123 Jan 21 21:41 /dev/hsmp
Characteristics of the dev node:
* Write mode is used for running set/configure commands
* Read mode is used for running get/status monitor commands
Access restrictions:
* Only root user is allowed to open the file in write mode.
* The file can be opened in read mode by all the users.
In-kernel integration:
* Other subsystems in the kernel can use the exported transport
function hsmp_send_message().
* Locking across callers is taken care by the driver.
An example
==========
To access hsmp device from a C program.
First, you need to include the headers::
#include <linux/amd_hsmp.h>
Which defines the supported messages/message IDs.
Next thing, open the device file, as follows::
int file;
file = open("/dev/hsmp", O_RDWR);
if (file < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong */
exit(1);
}
The following IOCTL is defined:
``ioctl(file, HSMP_IOCTL_CMD, struct hsmp_message *msg)``
The argument is a pointer to a::
struct hsmp_message {
__u32 msg_id; /* Message ID */
__u16 num_args; /* Number of input argument words in message */
__u16 response_sz; /* Number of expected output/response words */
__u32 args[HSMP_MAX_MSG_LEN]; /* argument/response buffer */
__u16 sock_ind; /* socket number */
};
The ioctl would return a non-zero on failure; you can read errno to see
what happened. The transaction returns 0 on success.
More details on the interface and message definitions can be found in chapter
"7 Host System Management Port (HSMP)" of the respective family/model PPR
eg: https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
User space C-APIs are made available by linking against the esmi library,
which is provided by the E-SMS project https://developer.amd.com/e-sms/.
See: https://github.com/amd/esmi_ib_library
...@@ -25,6 +25,7 @@ x86-specific Documentation ...@@ -25,6 +25,7 @@ x86-specific Documentation
intel-iommu intel-iommu
intel_txt intel_txt
amd-memory-encryption amd-memory-encryption
amd_hsmp
pti pti
mds mds
microcode microcode
......
...@@ -989,6 +989,16 @@ L: platform-driver-x86@vger.kernel.org ...@@ -989,6 +989,16 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained S: Maintained
F: drivers/platform/x86/amd-pmc.* F: drivers/platform/x86/amd-pmc.*
AMD HSMP DRIVER
M: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
R: Carlos Bilbao <carlos.bilbao@amd.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/x86/amd_hsmp.rst
F: arch/x86/include/asm/amd_hsmp.h
F: arch/x86/include/uapi/asm/amd_hsmp.h
F: drivers/platform/x86/amd_hsmp.c
AMD POWERPLAY AND SWSMU AMD POWERPLAY AND SWSMU
M: Evan Quan <evan.quan@amd.com> M: Evan Quan <evan.quan@amd.com>
L: amd-gfx@lists.freedesktop.org L: amd-gfx@lists.freedesktop.org
...@@ -9934,6 +9944,13 @@ S: Maintained ...@@ -9934,6 +9944,13 @@ S: Maintained
F: arch/x86/include/asm/intel_scu_ipc.h F: arch/x86/include/asm/intel_scu_ipc.h
F: drivers/platform/x86/intel_scu_* F: drivers/platform/x86/intel_scu_*
INTEL SDSI DRIVER
M: David E. Box <david.e.box@linux.intel.com>
S: Supported
F: drivers/platform/x86/intel/sdsi.c
F: tools/arch/x86/intel_sdsi/
F: tools/testing/selftests/drivers/sdsi/
INTEL SKYLAKE INT3472 ACPI DEVICE DRIVER INTEL SKYLAKE INT3472 ACPI DEVICE DRIVER
M: Daniel Scally <djrscally@gmail.com> M: Daniel Scally <djrscally@gmail.com>
S: Maintained S: Maintained
...@@ -9970,7 +9987,7 @@ INTEL UNCORE FREQUENCY CONTROL ...@@ -9970,7 +9987,7 @@ INTEL UNCORE FREQUENCY CONTROL
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org L: platform-driver-x86@vger.kernel.org
S: Maintained S: Maintained
F: drivers/platform/x86/intel/uncore-frequency.c F: drivers/platform/x86/intel/uncore-frequency/
INTEL VENDOR SPECIFIC EXTENDED CAPABILITIES DRIVER INTEL VENDOR SPECIFIC EXTENDED CAPABILITIES DRIVER
M: David E. Box <david.e.box@linux.intel.com> M: David E. Box <david.e.box@linux.intel.com>
......
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_X86_AMD_HSMP_H_
#define _ASM_X86_AMD_HSMP_H_
#include <uapi/asm/amd_hsmp.h>
#if IS_ENABLED(CONFIG_AMD_HSMP)
int hsmp_send_message(struct hsmp_message *msg);
#else
static inline int hsmp_send_message(struct hsmp_message *msg)
{
return -ENODEV;
}
#endif
#endif /*_ASM_X86_AMD_HSMP_H_*/
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_ASM_X86_AMD_HSMP_H_
#define _UAPI_ASM_X86_AMD_HSMP_H_
#include <linux/types.h>
#pragma pack(4)
#define HSMP_MAX_MSG_LEN 8
/*
* HSMP Messages supported
*/
enum hsmp_message_ids {
HSMP_TEST = 1, /* 01h Increments input value by 1 */
HSMP_GET_SMU_VER, /* 02h SMU FW version */
HSMP_GET_PROTO_VER, /* 03h HSMP interface version */
HSMP_GET_SOCKET_POWER, /* 04h average package power consumption */
HSMP_SET_SOCKET_POWER_LIMIT, /* 05h Set the socket power limit */
HSMP_GET_SOCKET_POWER_LIMIT, /* 06h Get current socket power limit */
HSMP_GET_SOCKET_POWER_LIMIT_MAX,/* 07h Get maximum socket power value */
HSMP_SET_BOOST_LIMIT, /* 08h Set a core maximum frequency limit */
HSMP_SET_BOOST_LIMIT_SOCKET, /* 09h Set socket maximum frequency level */
HSMP_GET_BOOST_LIMIT, /* 0Ah Get current frequency limit */
HSMP_GET_PROC_HOT, /* 0Bh Get PROCHOT status */
HSMP_SET_XGMI_LINK_WIDTH, /* 0Ch Set max and min width of xGMI Link */
HSMP_SET_DF_PSTATE, /* 0Dh Alter APEnable/Disable messages behavior */
HSMP_SET_AUTO_DF_PSTATE, /* 0Eh Enable DF P-State Performance Boost algorithm */
HSMP_GET_FCLK_MCLK, /* 0Fh Get FCLK and MEMCLK for current socket */
HSMP_GET_CCLK_THROTTLE_LIMIT, /* 10h Get CCLK frequency limit in socket */
HSMP_GET_C0_PERCENT, /* 11h Get average C0 residency in socket */
HSMP_SET_NBIO_DPM_LEVEL, /* 12h Set max/min LCLK DPM Level for a given NBIO */
/* 13h Reserved */
HSMP_GET_DDR_BANDWIDTH = 0x14, /* 14h Get theoretical maximum and current DDR Bandwidth */
HSMP_GET_TEMP_MONITOR, /* 15h Get per-DIMM temperature and refresh rates */
HSMP_MSG_ID_MAX,
};
struct hsmp_message {
__u32 msg_id; /* Message ID */
__u16 num_args; /* Number of input argument words in message */
__u16 response_sz; /* Number of expected output/response words */
__u32 args[HSMP_MAX_MSG_LEN]; /* argument/response buffer */
__u16 sock_ind; /* socket number */
};
enum hsmp_msg_type {
HSMP_RSVD = -1,
HSMP_SET = 0,
HSMP_GET = 1,
};
struct hsmp_msg_desc {
int num_args;
int response_sz;
enum hsmp_msg_type type;
};
/*
* User may use these comments as reference, please find the
* supported list of messages and message definition in the
* HSMP chapter of respective family/model PPR.
*
* Not supported messages would return -ENOMSG.
*/
static const struct hsmp_msg_desc hsmp_msg_desc_table[] = {
/* RESERVED */
{0, 0, HSMP_RSVD},
/*
* HSMP_TEST, num_args = 1, response_sz = 1
* input: args[0] = xx
* output: args[0] = xx + 1
*/
{1, 1, HSMP_GET},
/*
* HSMP_GET_SMU_VER, num_args = 0, response_sz = 1
* output: args[0] = smu fw ver
*/
{0, 1, HSMP_GET},
/*
* HSMP_GET_PROTO_VER, num_args = 0, response_sz = 1
* output: args[0] = proto version
*/
{0, 1, HSMP_GET},
/*
* HSMP_GET_SOCKET_POWER, num_args = 0, response_sz = 1
* output: args[0] = socket power in mWatts
*/
{0, 1, HSMP_GET},
/*
* HSMP_SET_SOCKET_POWER_LIMIT, num_args = 1, response_sz = 0
* input: args[0] = power limit value in mWatts
*/
{1, 0, HSMP_SET},
/*
* HSMP_GET_SOCKET_POWER_LIMIT, num_args = 0, response_sz = 1
* output: args[0] = socket power limit value in mWatts
*/
{0, 1, HSMP_GET},
/*
* HSMP_GET_SOCKET_POWER_LIMIT_MAX, num_args = 0, response_sz = 1
* output: args[0] = maximuam socket power limit in mWatts
*/
{0, 1, HSMP_GET},
/*
* HSMP_SET_BOOST_LIMIT, num_args = 1, response_sz = 0
* input: args[0] = apic id[31:16] + boost limit value in MHz[15:0]
*/
{1, 0, HSMP_SET},
/*
* HSMP_SET_BOOST_LIMIT_SOCKET, num_args = 1, response_sz = 0
* input: args[0] = boost limit value in MHz
*/
{1, 0, HSMP_SET},
/*
* HSMP_GET_BOOST_LIMIT, num_args = 1, response_sz = 1
* input: args[0] = apic id
* output: args[0] = boost limit value in MHz
*/
{1, 1, HSMP_GET},
/*
* HSMP_GET_PROC_HOT, num_args = 0, response_sz = 1
* output: args[0] = proc hot status
*/
{0, 1, HSMP_GET},
/*
* HSMP_SET_XGMI_LINK_WIDTH, num_args = 1, response_sz = 0
* input: args[0] = min link width[15:8] + max link width[7:0]
*/
{1, 0, HSMP_SET},
/*
* HSMP_SET_DF_PSTATE, num_args = 1, response_sz = 0
* input: args[0] = df pstate[7:0]
*/
{1, 0, HSMP_SET},
/* HSMP_SET_AUTO_DF_PSTATE, num_args = 0, response_sz = 0 */
{0, 0, HSMP_SET},
/*
* HSMP_GET_FCLK_MCLK, num_args = 0, response_sz = 2
* output: args[0] = fclk in MHz, args[1] = mclk in MHz
*/
{0, 2, HSMP_GET},
/*
* HSMP_GET_CCLK_THROTTLE_LIMIT, num_args = 0, response_sz = 1
* output: args[0] = core clock in MHz
*/
{0, 1, HSMP_GET},
/*
* HSMP_GET_C0_PERCENT, num_args = 0, response_sz = 1
* output: args[0] = average c0 residency
*/
{0, 1, HSMP_GET},
/*
* HSMP_SET_NBIO_DPM_LEVEL, num_args = 1, response_sz = 0
* input: args[0] = nbioid[23:16] + max dpm level[15:8] + min dpm level[7:0]
*/
{1, 0, HSMP_SET},
/* RESERVED message */
{0, 0, HSMP_RSVD},
/*
* HSMP_GET_DDR_BANDWIDTH, num_args = 0, response_sz = 1
* output: args[0] = max bw in Gbps[31:20] + utilised bw in Gbps[19:8] +
* bw in percentage[7:0]
*/
{0, 1, HSMP_GET},
/*
* HSMP_GET_TEMP_MONITOR, num_args = 0, response_sz = 1
* output: args[0] = temperature in degree celsius. [15:8] integer part +
* [7:5] fractional part
*/
{0, 1, HSMP_GET},
};
/* Reset to default packing */
#pragma pack()
/* Define unique ioctl command for hsmp msgs using generic _IOWR */
#define HSMP_BASE_IOCTL_NR 0xF8
#define HSMP_IOCTL_CMD _IOWR(HSMP_BASE_IOCTL_NR, 0, struct hsmp_message)
#endif /*_ASM_X86_AMD_HSMP_H_*/
...@@ -1750,6 +1750,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) ...@@ -1750,6 +1750,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
{"INT3515", }, {"INT3515", },
/* Non-conforming _HID for Cirrus Logic already released */ /* Non-conforming _HID for Cirrus Logic already released */
{"CLSA0100", }, {"CLSA0100", },
/*
* Some ACPI devs contain SerialBus resources even though they are not
* attached to a serial bus at all.
*/
{"MSHW0028", },
/* /*
* HIDs of device with an UartSerialBusV2 resource for which userspace * HIDs of device with an UartSerialBusV2 resource for which userspace
* expects a regular tty cdev to be created (instead of the in kernel * expects a regular tty cdev to be created (instead of the in kernel
......
...@@ -86,6 +86,8 @@ struct lpi_device_constraint_amd { ...@@ -86,6 +86,8 @@ struct lpi_device_constraint_amd {
int min_dstate; int min_dstate;
}; };
static LIST_HEAD(lps0_s2idle_devops_head);
static struct lpi_constraints *lpi_constraints_table; static struct lpi_constraints *lpi_constraints_table;
static int lpi_constraints_table_size; static int lpi_constraints_table_size;
static int rev_id; static int rev_id;
...@@ -440,6 +442,8 @@ static struct acpi_scan_handler lps0_handler = { ...@@ -440,6 +442,8 @@ static struct acpi_scan_handler lps0_handler = {
int acpi_s2idle_prepare_late(void) int acpi_s2idle_prepare_late(void)
{ {
struct acpi_s2idle_dev_ops *handler;
if (!lps0_device_handle || sleep_no_lps0) if (!lps0_device_handle || sleep_no_lps0)
return 0; return 0;
...@@ -470,14 +474,26 @@ int acpi_s2idle_prepare_late(void) ...@@ -470,14 +474,26 @@ int acpi_s2idle_prepare_late(void)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY, acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft); lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
} }
list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
if (handler->prepare)
handler->prepare();
}
return 0; return 0;
} }
void acpi_s2idle_restore_early(void) void acpi_s2idle_restore_early(void)
{ {
struct acpi_s2idle_dev_ops *handler;
if (!lps0_device_handle || sleep_no_lps0) if (!lps0_device_handle || sleep_no_lps0)
return; return;
list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node)
if (handler->restore)
handler->restore();
/* Modern standby exit */ /* Modern standby exit */
if (lps0_dsm_func_mask_microsoft > 0) if (lps0_dsm_func_mask_microsoft > 0)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT, acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
...@@ -520,4 +536,28 @@ void acpi_s2idle_setup(void) ...@@ -520,4 +536,28 @@ void acpi_s2idle_setup(void)
s2idle_set_ops(&acpi_s2idle_ops_lps0); s2idle_set_ops(&acpi_s2idle_ops_lps0);
} }
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
{
if (!lps0_device_handle || sleep_no_lps0)
return -ENODEV;
lock_system_sleep();
list_add(&arg->list_node, &lps0_s2idle_devops_head);
unlock_system_sleep();
return 0;
}
EXPORT_SYMBOL_GPL(acpi_register_lps0_dev);
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg)
{
if (!lps0_device_handle || sleep_no_lps0)
return;
lock_system_sleep();
list_del(&arg->list_node);
unlock_system_sleep();
}
EXPORT_SYMBOL_GPL(acpi_unregister_lps0_dev);
#endif /* CONFIG_SUSPEND */ #endif /* CONFIG_SUSPEND */
...@@ -469,6 +469,27 @@ static const struct soc_device_data soc_device_INT33D3 = { ...@@ -469,6 +469,27 @@ static const struct soc_device_data soc_device_INT33D3 = {
.button_info = soc_button_INT33D3, .button_info = soc_button_INT33D3,
}; };
/*
* Button info for Microsoft Surface 3 (non pro), this is indentical to
* the PNP0C40 info except that the home button is active-high.
*
* The Surface 3 Pro also has a MSHW0028 ACPI device, but that uses a custom
* version of the drivers/platform/x86/intel/hid.c 5 button array ACPI API
* instead. A check() callback is not necessary though as the Surface 3 Pro
* MSHW0028 ACPI device's resource table does not contain any GPIOs.
*/
static const struct soc_button_info soc_button_MSHW0028[] = {
{ "power", 0, EV_KEY, KEY_POWER, false, true, true },
{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true, false },
{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
{ "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
{ }
};
static const struct soc_device_data soc_device_MSHW0028 = {
.button_info = soc_button_MSHW0028,
};
/* /*
* Special device check for Surface Book 2 and Surface Pro (2017). * Special device check for Surface Book 2 and Surface Pro (2017).
* Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
...@@ -535,7 +556,8 @@ static const struct acpi_device_id soc_button_acpi_match[] = { ...@@ -535,7 +556,8 @@ static const struct acpi_device_id soc_button_acpi_match[] = {
{ "ID9001", (unsigned long)&soc_device_INT33D3 }, { "ID9001", (unsigned long)&soc_device_INT33D3 },
{ "ACPI0011", 0 }, { "ACPI0011", 0 },
/* Microsoft Surface Devices (5th and 6th generation) */ /* Microsoft Surface Devices (3th, 5th and 6th generation) */
{ "MSHW0028", (unsigned long)&soc_device_MSHW0028 },
{ "MSHW0040", (unsigned long)&soc_device_MSHW0040 }, { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
{ } { }
......
...@@ -443,6 +443,9 @@ static const unsigned int byt_sus_pcu_spi_pins[] = { 21 }; ...@@ -443,6 +443,9 @@ static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 }; static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 };
static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 }; static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 };
static const unsigned int byt_sus_pmu_clk1_pins[] = { 5 };
static const unsigned int byt_sus_pmu_clk2_pins[] = { 6 };
static const struct intel_pingroup byt_sus_groups[] = { static const struct intel_pingroup byt_sus_groups[] = {
PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values), PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values),
PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values), PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values),
...@@ -450,20 +453,27 @@ static const struct intel_pingroup byt_sus_groups[] = { ...@@ -450,20 +453,27 @@ static const struct intel_pingroup byt_sus_groups[] = {
PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values), PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values), PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values), PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
PIN_GROUP("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
PIN_GROUP("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
}; };
static const char * const byt_sus_usb_groups[] = { static const char * const byt_sus_usb_groups[] = {
"usb_oc_grp", "usb_ulpi_grp", "usb_oc_grp", "usb_ulpi_grp",
}; };
static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" }; static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
static const char * const byt_sus_pmu_clk_groups[] = {
"pmu_clk1_grp", "pmu_clk2_grp",
};
static const char * const byt_sus_gpio_groups[] = { static const char * const byt_sus_gpio_groups[] = {
"usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio", "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
"pmu_clk1_grp", "pmu_clk2_grp",
}; };
static const struct intel_function byt_sus_functions[] = { static const struct intel_function byt_sus_functions[] = {
FUNCTION("usb", byt_sus_usb_groups), FUNCTION("usb", byt_sus_usb_groups),
FUNCTION("spi", byt_sus_spi_groups), FUNCTION("spi", byt_sus_spi_groups),
FUNCTION("gpio", byt_sus_gpio_groups), FUNCTION("gpio", byt_sus_gpio_groups),
FUNCTION("pmu_clk", byt_sus_pmu_clk_groups),
}; };
static const struct intel_community byt_sus_communities[] = { static const struct intel_community byt_sus_communities[] = {
......
...@@ -28,13 +28,6 @@ config SURFACE3_WMI ...@@ -28,13 +28,6 @@ config SURFACE3_WMI
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called surface3-wmi. be called surface3-wmi.
config SURFACE_3_BUTTON
tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet"
depends on ACPI
depends on KEYBOARD_GPIO && I2C
help
This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
config SURFACE_3_POWER_OPREGION config SURFACE_3_POWER_OPREGION
tristate "Surface 3 battery platform operation region support" tristate "Surface 3 battery platform operation region support"
depends on ACPI depends on ACPI
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
# #
obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o
obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o
obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/ obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
......
...@@ -116,14 +116,10 @@ static acpi_status s3_wmi_attach_spi_device(acpi_handle handle, ...@@ -116,14 +116,10 @@ static acpi_status s3_wmi_attach_spi_device(acpi_handle handle,
void *data, void *data,
void **return_value) void **return_value)
{ {
struct acpi_device *adev, **ts_adev; struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
struct acpi_device **ts_adev = data;
if (acpi_bus_get_device(handle, &adev)) if (!adev || strncmp(acpi_device_bid(adev), SPI_TS_OBJ_NAME,
return AE_OK;
ts_adev = data;
if (strncmp(acpi_device_bid(adev), SPI_TS_OBJ_NAME,
strlen(SPI_TS_OBJ_NAME))) strlen(SPI_TS_OBJ_NAME)))
return AE_OK; return AE_OK;
...@@ -190,14 +186,11 @@ static int s3_wmi_create_and_register_input(struct platform_device *pdev) ...@@ -190,14 +186,11 @@ static int s3_wmi_create_and_register_input(struct platform_device *pdev)
error = input_register_device(input); error = input_register_device(input);
if (error) if (error)
goto out_err; return error;
s3_wmi.input = input; s3_wmi.input = input;
return 0; return 0;
out_err:
input_free_device(s3_wmi.input);
return error;
} }
static int __init s3_wmi_probe(struct platform_device *pdev) static int __init s3_wmi_probe(struct platform_device *pdev)
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Supports for the button array on the Surface tablets.
*
* (C) Copyright 2016 Red Hat, Inc
*
* Based on soc_button_array.c:
*
* {C} Copyright 2014 Intel Corporation
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio_keys.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#define SURFACE_BUTTON_OBJ_NAME "TEV2"
#define MAX_NBUTTONS 4
/*
* Some of the buttons like volume up/down are auto repeat, while others
* are not. To support both, we register two platform devices, and put
* buttons into them based on whether the key should be auto repeat.
*/
#define BUTTON_TYPES 2
/*
* Power button, Home button, Volume buttons support is supposed to
* be covered by drivers/input/misc/soc_button_array.c, which is implemented
* according to "Windows ACPI Design Guide for SoC Platforms".
* However surface 3 seems not to obey the specs, instead it uses
* device TEV2(MSHW0028) for declaring the GPIOs. The gpios are also slightly
* different in which the Home button is active high.
* Compared to surfacepro3_button.c which also handles MSHW0028, the Surface 3
* is a reduce platform and thus uses GPIOs, not ACPI events.
* We choose an I2C driver here because we need to access the resources
* declared under the device node, while surfacepro3_button.c only needs
* the ACPI companion node.
*/
static const struct acpi_device_id surface3_acpi_match[] = {
{ "MSHW0028", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, surface3_acpi_match);
struct surface3_button_info {
const char *name;
int acpi_index;
unsigned int event_type;
unsigned int event_code;
bool autorepeat;
bool wakeup;
bool active_low;
};
struct surface3_button_data {
struct platform_device *children[BUTTON_TYPES];
};
/*
* Get the Nth GPIO number from the ACPI object.
*/
static int surface3_button_lookup_gpio(struct device *dev, int acpi_index)
{
struct gpio_desc *desc;
int gpio;
desc = gpiod_get_index(dev, NULL, acpi_index, GPIOD_ASIS);
if (IS_ERR(desc))
return PTR_ERR(desc);
gpio = desc_to_gpio(desc);
gpiod_put(desc);
return gpio;
}
static struct platform_device *
surface3_button_device_create(struct i2c_client *client,
const struct surface3_button_info *button_info,
bool autorepeat)
{
const struct surface3_button_info *info;
struct platform_device *pd;
struct gpio_keys_button *gpio_keys;
struct gpio_keys_platform_data *gpio_keys_pdata;
int n_buttons = 0;
int gpio;
int error;
gpio_keys_pdata = devm_kzalloc(&client->dev,
sizeof(*gpio_keys_pdata) +
sizeof(*gpio_keys) * MAX_NBUTTONS,
GFP_KERNEL);
if (!gpio_keys_pdata)
return ERR_PTR(-ENOMEM);
gpio_keys = (void *)(gpio_keys_pdata + 1);
for (info = button_info; info->name; info++) {
if (info->autorepeat != autorepeat)
continue;
gpio = surface3_button_lookup_gpio(&client->dev,
info->acpi_index);
if (!gpio_is_valid(gpio))
continue;
gpio_keys[n_buttons].type = info->event_type;
gpio_keys[n_buttons].code = info->event_code;
gpio_keys[n_buttons].gpio = gpio;
gpio_keys[n_buttons].active_low = info->active_low;
gpio_keys[n_buttons].desc = info->name;
gpio_keys[n_buttons].wakeup = info->wakeup;
n_buttons++;
}
if (n_buttons == 0) {
error = -ENODEV;
goto err_free_mem;
}
gpio_keys_pdata->buttons = gpio_keys;
gpio_keys_pdata->nbuttons = n_buttons;
gpio_keys_pdata->rep = autorepeat;
pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO);
if (!pd) {
error = -ENOMEM;
goto err_free_mem;
}
error = platform_device_add_data(pd, gpio_keys_pdata,
sizeof(*gpio_keys_pdata));
if (error)
goto err_free_pdev;
error = platform_device_add(pd);
if (error)
goto err_free_pdev;
return pd;
err_free_pdev:
platform_device_put(pd);
err_free_mem:
devm_kfree(&client->dev, gpio_keys_pdata);
return ERR_PTR(error);
}
static int surface3_button_remove(struct i2c_client *client)
{
struct surface3_button_data *priv = i2c_get_clientdata(client);
int i;
for (i = 0; i < BUTTON_TYPES; i++)
if (priv->children[i])
platform_device_unregister(priv->children[i]);
return 0;
}
static struct surface3_button_info surface3_button_surface3[] = {
{ "power", 0, EV_KEY, KEY_POWER, false, true, true },
{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true, false },
{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
{ "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
{ }
};
static int surface3_button_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct surface3_button_data *priv;
struct platform_device *pd;
int i;
int error;
if (strncmp(acpi_device_bid(ACPI_COMPANION(&client->dev)),
SURFACE_BUTTON_OBJ_NAME,
strlen(SURFACE_BUTTON_OBJ_NAME)))
return -ENODEV;
error = gpiod_count(dev, NULL);
if (error < 0) {
dev_dbg(dev, "no GPIO attached, ignoring...\n");
return error;
}
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
i2c_set_clientdata(client, priv);
for (i = 0; i < BUTTON_TYPES; i++) {
pd = surface3_button_device_create(client,
surface3_button_surface3,
i == 0);
if (IS_ERR(pd)) {
error = PTR_ERR(pd);
if (error != -ENODEV) {
surface3_button_remove(client);
return error;
}
continue;
}
priv->children[i] = pd;
}
if (!priv->children[0] && !priv->children[1])
return -ENODEV;
return 0;
}
static const struct i2c_device_id surface3_id[] = {
{ }
};
MODULE_DEVICE_TABLE(i2c, surface3_id);
static struct i2c_driver surface3_driver = {
.probe = surface3_button_probe,
.remove = surface3_button_remove,
.id_table = surface3_id,
.driver = {
.name = "surface3",
.acpi_match_table = ACPI_PTR(surface3_acpi_match),
},
};
module_i2c_driver(surface3_driver);
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
MODULE_DESCRIPTION("surface3 button array driver");
MODULE_LICENSE("GPL v2");
...@@ -770,7 +770,8 @@ static acpi_status san_consumer_setup(acpi_handle handle, u32 lvl, ...@@ -770,7 +770,8 @@ static acpi_status san_consumer_setup(acpi_handle handle, u32 lvl,
return AE_OK; return AE_OK;
/* Ignore ACPI devices that are not present. */ /* Ignore ACPI devices that are not present. */
if (acpi_bus_get_device(handle, &adev) != 0) adev = acpi_fetch_acpi_dev(handle);
if (!adev)
return AE_OK; return AE_OK;
san_consumer_dbg(&pdev->dev, handle, "creating device link\n"); san_consumer_dbg(&pdev->dev, handle, "creating device link\n");
......
...@@ -210,6 +210,19 @@ config AMD_PMC ...@@ -210,6 +210,19 @@ config AMD_PMC
If you choose to compile this driver as a module the module will be If you choose to compile this driver as a module the module will be
called amd-pmc. called amd-pmc.
config AMD_HSMP
tristate "AMD HSMP Driver"
depends on AMD_NB && X86_64
help
The driver provides a way for user space tools to monitor and manage
system management functionality on EPYC server CPUs from AMD.
Host System Management Port (HSMP) interface is a mailbox interface
between the x86 core and the System Management Unit (SMU) firmware.
If you choose to compile this driver as a module the module will be
called amd_hsmp.
config ADV_SWBUTTON config ADV_SWBUTTON
tristate "Advantech ACPI Software Button Driver" tristate "Advantech ACPI Software Button Driver"
depends on ACPI && INPUT depends on ACPI && INPUT
...@@ -915,6 +928,7 @@ config COMPAL_LAPTOP ...@@ -915,6 +928,7 @@ config COMPAL_LAPTOP
config LG_LAPTOP config LG_LAPTOP
tristate "LG Laptop Extras" tristate "LG Laptop Extras"
depends on ACPI depends on ACPI
depends on ACPI_BATTERY
depends on ACPI_WMI depends on ACPI_WMI
depends on INPUT depends on INPUT
select INPUT_SPARSEKMAP select INPUT_SPARSEKMAP
...@@ -1027,7 +1041,7 @@ config TOUCHSCREEN_DMI ...@@ -1027,7 +1041,7 @@ config TOUCHSCREEN_DMI
config X86_ANDROID_TABLETS config X86_ANDROID_TABLETS
tristate "X86 Android tablet support" tristate "X86 Android tablet support"
depends on I2C && SERIAL_DEV_BUS && ACPI && GPIOLIB depends on I2C && SPI && SERIAL_DEV_BUS && ACPI && EFI && GPIOLIB
help help
X86 tablets which ship with Android as (part of) the factory image X86 tablets which ship with Android as (part of) the factory image
typically have various problems with their DSDTs. The factory kernels typically have various problems with their DSDTs. The factory kernels
......
...@@ -24,6 +24,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o ...@@ -24,6 +24,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o
# AMD # AMD
obj-$(CONFIG_AMD_PMC) += amd-pmc.o obj-$(CONFIG_AMD_PMC) += amd-pmc.o
obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o
# Advantech # Advantech
obj-$(CONFIG_ADV_SWBUTTON) += adv_swbutton.o obj-$(CONFIG_ADV_SWBUTTON) += adv_swbutton.o
......
This diff is collapsed.
This diff is collapsed.
...@@ -284,6 +284,7 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd) ...@@ -284,6 +284,7 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd)
return ret; return ret;
} }
EXPORT_SYMBOL(dcdbas_smi_request);
/** /**
* smi_request_store: * smi_request_store:
...@@ -351,7 +352,6 @@ static ssize_t smi_request_store(struct device *dev, ...@@ -351,7 +352,6 @@ static ssize_t smi_request_store(struct device *dev,
mutex_unlock(&smi_data_lock); mutex_unlock(&smi_data_lock);
return ret; return ret;
} }
EXPORT_SYMBOL(dcdbas_smi_request);
/** /**
* host_control_smi: generate host control SMI * host_control_smi: generate host control SMI
......
This diff is collapsed.
...@@ -470,10 +470,17 @@ static DEVICE_ATTR_RW(charge_control_thresholds); ...@@ -470,10 +470,17 @@ static DEVICE_ATTR_RW(charge_control_thresholds);
static int huawei_wmi_battery_add(struct power_supply *battery) static int huawei_wmi_battery_add(struct power_supply *battery)
{ {
device_create_file(&battery->dev, &dev_attr_charge_control_start_threshold); int err = 0;
device_create_file(&battery->dev, &dev_attr_charge_control_end_threshold);
return 0; err = device_create_file(&battery->dev, &dev_attr_charge_control_start_threshold);
if (err)
return err;
err = device_create_file(&battery->dev, &dev_attr_charge_control_end_threshold);
if (err)
device_remove_file(&battery->dev, &dev_attr_charge_control_start_threshold);
return err;
} }
static int huawei_wmi_battery_remove(struct power_supply *battery) static int huawei_wmi_battery_remove(struct power_supply *battery)
......
...@@ -5,13 +5,14 @@ ...@@ -5,13 +5,14 @@
source "drivers/platform/x86/intel/atomisp2/Kconfig" source "drivers/platform/x86/intel/atomisp2/Kconfig"
source "drivers/platform/x86/intel/int1092/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/int3472/Kconfig"
source "drivers/platform/x86/intel/pmc/Kconfig" source "drivers/platform/x86/intel/pmc/Kconfig"
source "drivers/platform/x86/intel/pmt/Kconfig" source "drivers/platform/x86/intel/pmt/Kconfig"
source "drivers/platform/x86/intel/speed_select_if/Kconfig" source "drivers/platform/x86/intel/speed_select_if/Kconfig"
source "drivers/platform/x86/intel/telemetry/Kconfig" source "drivers/platform/x86/intel/telemetry/Kconfig"
source "drivers/platform/x86/intel/wmi/Kconfig" source "drivers/platform/x86/intel/wmi/Kconfig"
source "drivers/platform/x86/intel/uncore-frequency/Kconfig"
config INTEL_HID_EVENT config INTEL_HID_EVENT
tristate "Intel HID Event" tristate "Intel HID Event"
...@@ -89,6 +90,26 @@ config INTEL_CHTDC_TI_PWRBTN ...@@ -89,6 +90,26 @@ config INTEL_CHTDC_TI_PWRBTN
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called intel_chtdc_ti_pwrbtn. will be called intel_chtdc_ti_pwrbtn.
config INTEL_CHTWC_INT33FE
tristate "Intel Cherry Trail Whiskey Cove ACPI INT33FE Driver"
depends on X86 && ACPI && I2C && REGULATOR
depends on CHARGER_BQ24190=y || (CHARGER_BQ24190=m && m)
depends on USB_ROLES_INTEL_XHCI=y || (USB_ROLES_INTEL_XHCI=m && m)
depends on TYPEC_MUX_PI3USB30532=y || (TYPEC_MUX_PI3USB30532=m && m)
help
This driver add support for the Intel Cherry Trail Whiskey Cove
INT33FE ACPI device found on the GPD win and the GPD pocket.
The INT33FE ACPI device on these mini laptops contains I2cSerialBusV2
resources for a MAX17042 Fuel Gauge, FUSB302 USB Type-C Controller
and PI3USB30532 USB switch.
This driver instantiates i2c-clients for these, so that standard
i2c drivers for these chips can bind to the them.
If you enable this driver it is advised to also select
CONFIG_TYPEC_FUSB302=m, CONFIG_TYPEC_MUX_PI3USB30532=m and
CONFIG_BATTERY_MAX17042=m.
config INTEL_ISHTP_ECLITE config INTEL_ISHTP_ECLITE
tristate "Intel ISHTP eclite controller Driver" tristate "Intel ISHTP eclite controller Driver"
depends on INTEL_ISH_HID depends on INTEL_ISH_HID
...@@ -134,6 +155,18 @@ config INTEL_RST ...@@ -134,6 +155,18 @@ config INTEL_RST
firmware will copy the memory contents back to RAM and resume the OS firmware will copy the memory contents back to RAM and resume the OS
as usual. as usual.
config INTEL_SDSI
tristate "Intel Software Defined Silicon Driver"
depends on INTEL_VSEC
depends on X86_64
help
This driver enables access to the Intel Software Defined Silicon
interface used to provision silicon features with an authentication
certificate and capability license.
To compile this driver as a module, choose M here: the module will
be called intel_sdsi.
config INTEL_SMARTCONNECT config INTEL_SMARTCONNECT
tristate "Intel Smart Connect disabling driver" tristate "Intel Smart Connect disabling driver"
depends on ACPI depends on ACPI
...@@ -159,18 +192,6 @@ config INTEL_TURBO_MAX_3 ...@@ -159,18 +192,6 @@ config INTEL_TURBO_MAX_3
This driver is only required when the system is not using Hardware 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. 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_VSEC config INTEL_VSEC
tristate "Intel Vendor Specific Extended Capabilities Driver" tristate "Intel Vendor Specific Extended Capabilities Driver"
depends on PCI depends on PCI
......
...@@ -6,13 +6,14 @@ ...@@ -6,13 +6,14 @@
obj-$(CONFIG_INTEL_ATOMISP2_PDX86) += atomisp2/ obj-$(CONFIG_INTEL_ATOMISP2_PDX86) += atomisp2/
obj-$(CONFIG_INTEL_SAR_INT1092) += int1092/ obj-$(CONFIG_INTEL_SAR_INT1092) += int1092/
obj-$(CONFIG_INTEL_CHT_INT33FE) += int33fe/
obj-$(CONFIG_INTEL_SKL_INT3472) += int3472/ obj-$(CONFIG_INTEL_SKL_INT3472) += int3472/
obj-$(CONFIG_INTEL_PMC_CORE) += pmc/ obj-$(CONFIG_INTEL_PMC_CORE) += pmc/
obj-$(CONFIG_INTEL_PMT_CLASS) += pmt/ obj-$(CONFIG_INTEL_PMT_CLASS) += pmt/
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += speed_select_if/ obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += speed_select_if/
obj-$(CONFIG_INTEL_TELEMETRY) += telemetry/ obj-$(CONFIG_INTEL_TELEMETRY) += telemetry/
obj-$(CONFIG_INTEL_WMI) += wmi/ obj-$(CONFIG_INTEL_WMI) += wmi/
obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += uncore-frequency/
# Intel input drivers # Intel input drivers
intel-hid-y := hid.o intel-hid-y := hid.o
...@@ -26,6 +27,8 @@ intel_int0002_vgpio-y := int0002_vgpio.o ...@@ -26,6 +27,8 @@ intel_int0002_vgpio-y := int0002_vgpio.o
obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
intel_oaktrail-y := oaktrail.o intel_oaktrail-y := oaktrail.o
obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o
intel_sdsi-y := sdsi.o
obj-$(CONFIG_INTEL_SDSI) += intel_sdsi.o
intel_vsec-y := vsec.o intel_vsec-y := vsec.o
obj-$(CONFIG_INTEL_VSEC) += intel_vsec.o obj-$(CONFIG_INTEL_VSEC) += intel_vsec.o
...@@ -36,6 +39,8 @@ intel_crystal_cove_charger-y := crystal_cove_charger.o ...@@ -36,6 +39,8 @@ intel_crystal_cove_charger-y := crystal_cove_charger.o
obj-$(CONFIG_X86_ANDROID_TABLETS) += intel_crystal_cove_charger.o obj-$(CONFIG_X86_ANDROID_TABLETS) += intel_crystal_cove_charger.o
intel_chtdc_ti_pwrbtn-y := chtdc_ti_pwrbtn.o intel_chtdc_ti_pwrbtn-y := chtdc_ti_pwrbtn.o
obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN) += intel_chtdc_ti_pwrbtn.o
intel_chtwc_int33fe-y := chtwc_int33fe.o
obj-$(CONFIG_INTEL_CHTWC_INT33FE) += intel_chtwc_int33fe.o
intel_mrfld_pwrbtn-y := mrfld_pwrbtn.o intel_mrfld_pwrbtn-y := mrfld_pwrbtn.o
obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o
intel_punit_ipc-y := punit_ipc.o intel_punit_ipc-y := punit_ipc.o
...@@ -48,5 +53,3 @@ intel-smartconnect-y := smartconnect.o ...@@ -48,5 +53,3 @@ intel-smartconnect-y := smartconnect.o
obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
intel_turbo_max_3-y := turbo_max_3.o intel_turbo_max_3-y := turbo_max_3.o
obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_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
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* for these chips can bind to the them. * for these chips can bind to the them.
*/ */
#include <linux/dmi.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -26,7 +27,12 @@ ...@@ -26,7 +27,12 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb/pd.h> #include <linux/usb/pd.h>
#include "intel_cht_int33fe_common.h" struct cht_int33fe_data {
struct i2c_client *battery_fg;
struct i2c_client *fusb302;
struct i2c_client *pi3usb30532;
struct fwnode_handle *dp;
};
/* /*
* Grrr, I severely dislike buggy BIOS-es. At least one BIOS enumerates * Grrr, I severely dislike buggy BIOS-es. At least one BIOS enumerates
...@@ -272,15 +278,44 @@ cht_int33fe_register_max17047(struct device *dev, struct cht_int33fe_data *data) ...@@ -272,15 +278,44 @@ cht_int33fe_register_max17047(struct device *dev, struct cht_int33fe_data *data)
return PTR_ERR_OR_ZERO(data->battery_fg); return PTR_ERR_OR_ZERO(data->battery_fg);
} }
int cht_int33fe_typec_probe(struct cht_int33fe_data *data) static const struct dmi_system_id cht_int33fe_typec_ids[] = {
{
/*
* GPD win / GPD pocket mini laptops
*
* This DMI match may not seem unique, but it is. In the 67000+
* DMI decode dumps from linux-hardware.org only 116 have
* board_vendor set to "AMI Corporation" and of those 116 only
* the GPD win's and pocket's board_name is "Default string".
*/
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
},
},
{ }
};
MODULE_DEVICE_TABLE(dmi, cht_int33fe_typec_ids);
static int cht_int33fe_typec_probe(struct platform_device *pdev)
{ {
struct device *dev = data->dev;
struct i2c_board_info board_info; struct i2c_board_info board_info;
struct device *dev = &pdev->dev;
struct cht_int33fe_data *data;
struct fwnode_handle *fwnode; struct fwnode_handle *fwnode;
struct regulator *regulator; struct regulator *regulator;
int fusb302_irq; int fusb302_irq;
int ret; int ret;
if (!dmi_check_system(cht_int33fe_typec_ids))
return -ENODEV;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
/* /*
* We expect the WC PMIC to be paired with a TI bq24292i charger-IC. * We expect the WC PMIC to be paired with a TI bq24292i charger-IC.
* We check for the bq24292i vbus regulator here, this has 2 purposes: * We check for the bq24292i vbus regulator here, this has 2 purposes:
...@@ -368,8 +403,10 @@ int cht_int33fe_typec_probe(struct cht_int33fe_data *data) ...@@ -368,8 +403,10 @@ int cht_int33fe_typec_probe(struct cht_int33fe_data *data)
return ret; return ret;
} }
int cht_int33fe_typec_remove(struct cht_int33fe_data *data) static int cht_int33fe_typec_remove(struct platform_device *pdev)
{ {
struct cht_int33fe_data *data = platform_get_drvdata(pdev);
i2c_unregister_device(data->pi3usb30532); i2c_unregister_device(data->pi3usb30532);
i2c_unregister_device(data->fusb302); i2c_unregister_device(data->fusb302);
i2c_unregister_device(data->battery_fg); i2c_unregister_device(data->battery_fg);
...@@ -378,3 +415,23 @@ int cht_int33fe_typec_remove(struct cht_int33fe_data *data) ...@@ -378,3 +415,23 @@ int cht_int33fe_typec_remove(struct cht_int33fe_data *data)
return 0; return 0;
} }
static const struct acpi_device_id cht_int33fe_acpi_ids[] = {
{ "INT33FE", },
{ }
};
static struct platform_driver cht_int33fe_typec_driver = {
.driver = {
.name = "Intel Cherry Trail ACPI INT33FE Type-C driver",
.acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids),
},
.probe = cht_int33fe_typec_probe,
.remove = cht_int33fe_typec_remove,
};
module_platform_driver(cht_int33fe_typec_driver);
MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE Type-C pseudo device driver");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL v2");
...@@ -726,12 +726,9 @@ static acpi_status __init ...@@ -726,12 +726,9 @@ static acpi_status __init
check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv)
{ {
const struct acpi_device_id *ids = context; const struct acpi_device_id *ids = context;
struct acpi_device *dev; struct acpi_device *dev = acpi_fetch_acpi_dev(handle);
if (acpi_bus_get_device(handle, &dev) != 0) if (dev && acpi_match_device_ids(dev, ids) == 0)
return AE_OK;
if (acpi_match_device_ids(dev, ids) == 0)
if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL))) if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL)))
dev_info(&dev->dev, dev_info(&dev->dev,
"intel-hid: created platform device\n"); "intel-hid: created platform device\n");
......
# SPDX-License-Identifier: GPL-2.0-only
config INTEL_CHT_INT33FE
tristate "Intel Cherry Trail ACPI INT33FE Driver"
depends on X86 && ACPI && I2C && REGULATOR
depends on CHARGER_BQ24190=y || (CHARGER_BQ24190=m && m)
depends on USB_ROLES_INTEL_XHCI=y || (USB_ROLES_INTEL_XHCI=m && m)
depends on TYPEC_MUX_PI3USB30532=y || (TYPEC_MUX_PI3USB30532=m && m)
help
This driver add support for the INT33FE ACPI device found on
some Intel Cherry Trail devices.
There are two kinds of INT33FE ACPI device possible: for hardware
with USB Type-C and Micro-B connectors. This driver supports both.
The INT33FE ACPI device has a CRS table with I2cSerialBusV2
resources for Fuel Gauge Controller and (in the Type-C variant)
FUSB302 USB Type-C Controller and PI3USB30532 USB switch.
This driver instantiates i2c-clients for these, so that standard
i2c drivers for these chips can bind to the them.
If you enable this driver it is advised to also select
CONFIG_BATTERY_BQ27XXX=m or CONFIG_BATTERY_BQ27XXX_I2C=m for Micro-B
device and CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m
for Type-C device.
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
intel_cht_int33fe-y := intel_cht_int33fe_common.o \
intel_cht_int33fe_typec.o \
intel_cht_int33fe_microb.o
// SPDX-License-Identifier: GPL-2.0
/*
* Common code for Intel Cherry Trail ACPI INT33FE pseudo device drivers
* (USB Micro-B and Type-C connector variants).
*
* Copyright (c) 2019 Yauhen Kharuzhy <jekhor@gmail.com>
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "intel_cht_int33fe_common.h"
#define EXPECTED_PTYPE 4
static int cht_int33fe_check_hw_type(struct device *dev)
{
unsigned long long ptyp;
acpi_status status;
int ret;
status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp);
if (ACPI_FAILURE(status)) {
dev_err(dev, "Error getting PTYPE\n");
return -ENODEV;
}
/*
* The same ACPI HID is used for different configurations check PTYP
* to ensure that we are dealing with the expected config.
*/
if (ptyp != EXPECTED_PTYPE)
return -ENODEV;
/* Check presence of INT34D3 (hardware-rev 3) expected for ptype == 4 */
if (!acpi_dev_present("INT34D3", "1", 3)) {
dev_err(dev, "Error PTYPE == %d, but no INT34D3 device\n",
EXPECTED_PTYPE);
return -ENODEV;
}
ret = i2c_acpi_client_count(ACPI_COMPANION(dev));
if (ret < 0)
return ret;
switch (ret) {
case 2:
return INT33FE_HW_MICROB;
case 4:
return INT33FE_HW_TYPEC;
default:
return -ENODEV;
}
}
static int cht_int33fe_probe(struct platform_device *pdev)
{
struct cht_int33fe_data *data;
struct device *dev = &pdev->dev;
int ret;
ret = cht_int33fe_check_hw_type(dev);
if (ret < 0)
return ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->dev = dev;
switch (ret) {
case INT33FE_HW_MICROB:
data->probe = cht_int33fe_microb_probe;
data->remove = cht_int33fe_microb_remove;
break;
case INT33FE_HW_TYPEC:
data->probe = cht_int33fe_typec_probe;
data->remove = cht_int33fe_typec_remove;
break;
}
platform_set_drvdata(pdev, data);
return data->probe(data);
}
static int cht_int33fe_remove(struct platform_device *pdev)
{
struct cht_int33fe_data *data = platform_get_drvdata(pdev);
return data->remove(data);
}
static const struct acpi_device_id cht_int33fe_acpi_ids[] = {
{ "INT33FE", },
{ }
};
MODULE_DEVICE_TABLE(acpi, cht_int33fe_acpi_ids);
static struct platform_driver cht_int33fe_driver = {
.driver = {
.name = "Intel Cherry Trail ACPI INT33FE driver",
.acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids),
},
.probe = cht_int33fe_probe,
.remove = cht_int33fe_remove,
};
module_platform_driver(cht_int33fe_driver);
MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver");
MODULE_AUTHOR("Yauhen Kharuzhy <jekhor@gmail.com>");
MODULE_LICENSE("GPL v2");
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Common code for Intel Cherry Trail ACPI INT33FE pseudo device drivers
* (USB Micro-B and Type-C connector variants), header file
*
* Copyright (c) 2019 Yauhen Kharuzhy <jekhor@gmail.com>
*/
#ifndef _INTEL_CHT_INT33FE_COMMON_H
#define _INTEL_CHT_INT33FE_COMMON_H
#include <linux/device.h>
#include <linux/fwnode.h>
#include <linux/i2c.h>
enum int33fe_hw_type {
INT33FE_HW_MICROB,
INT33FE_HW_TYPEC,
};
struct cht_int33fe_data {
struct device *dev;
int (*probe)(struct cht_int33fe_data *data);
int (*remove)(struct cht_int33fe_data *data);
struct i2c_client *battery_fg;
/* Type-C only */
struct i2c_client *fusb302;
struct i2c_client *pi3usb30532;
struct fwnode_handle *dp;
};
int cht_int33fe_microb_probe(struct cht_int33fe_data *data);
int cht_int33fe_microb_remove(struct cht_int33fe_data *data);
int cht_int33fe_typec_probe(struct cht_int33fe_data *data);
int cht_int33fe_typec_remove(struct cht_int33fe_data *data);
#endif /* _INTEL_CHT_INT33FE_COMMON_H */
// SPDX-License-Identifier: GPL-2.0
/*
* Intel Cherry Trail ACPI INT33FE pseudo device driver for devices with
* USB Micro-B connector (e.g. without of FUSB302 USB Type-C controller)
*
* Copyright (C) 2019 Yauhen Kharuzhy <jekhor@gmail.com>
*
* At least one Intel Cherry Trail based device which ship with Windows 10
* (Lenovo YogaBook YB1-X91L/F tablet), have this weird INT33FE ACPI device
* with a CRS table with 2 I2cSerialBusV2 resources, for 2 different chips
* attached to various i2c busses:
* 1. The Whiskey Cove PMIC, which is also described by the INT34D3 ACPI device
* 2. TI BQ27542 Fuel Gauge Controller
*
* So this driver is a stub / pseudo driver whose only purpose is to
* instantiate i2c-client for battery fuel gauge, so that standard i2c driver
* for these chip can bind to the it.
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/usb/pd.h>
#include "intel_cht_int33fe_common.h"
static const char * const bq27xxx_suppliers[] = { "bq25890-charger" };
static const struct property_entry bq27xxx_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq27xxx_suppliers),
{ }
};
static const struct software_node bq27xxx_node = {
.properties = bq27xxx_props,
};
int cht_int33fe_microb_probe(struct cht_int33fe_data *data)
{
struct device *dev = data->dev;
struct i2c_board_info board_info;
memset(&board_info, 0, sizeof(board_info));
strscpy(board_info.type, "bq27542", ARRAY_SIZE(board_info.type));
board_info.dev_name = "bq27542";
board_info.swnode = &bq27xxx_node;
data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info);
return PTR_ERR_OR_ZERO(data->battery_fg);
}
int cht_int33fe_microb_remove(struct cht_int33fe_data *data)
{
i2c_unregister_device(data->battery_fg);
return 0;
}
...@@ -112,7 +112,6 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 ...@@ -112,7 +112,6 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347
struct acpi_device *adev; struct acpi_device *adev;
acpi_handle handle; acpi_handle handle;
acpi_status status; acpi_status status;
int ret;
if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) { if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
dev_warn(int3472->dev, "Too many GPIOs mapped\n"); dev_warn(int3472->dev, "Too many GPIOs mapped\n");
...@@ -139,8 +138,8 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 ...@@ -139,8 +138,8 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -EINVAL; return -EINVAL;
ret = acpi_bus_get_device(handle, &adev); adev = acpi_fetch_acpi_dev(handle);
if (ret) if (!adev)
return -ENODEV; return -ENODEV;
table_entry = &int3472->gpios.table[int3472->n_sensor_gpios]; table_entry = &int3472->gpios.table[int3472->n_sensor_gpios];
......
This diff is collapsed.
# SPDX-License-Identifier: GPL-2.0-only
#
# Uncore Frquency control drivers
#
menu "Intel Uncore Frequency Control"
depends on X86_64 || COMPILE_TEST
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.
endmenu
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for linux/drivers/platform/x86/intel/uncore-frequency
#
obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o
intel-uncore-frequency-y := uncore-frequency.o
obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency-common.o
intel-uncore-frequency-common-y := uncore-frequency-common.o
// SPDX-License-Identifier: GPL-2.0
/*
* Intel Uncore Frequency Control: Common code implementation
* Copyright (c) 2022, Intel Corporation.
* All rights reserved.
*
*/
#include <linux/cpu.h>
#include <linux/module.h>
#include "uncore-frequency-common.h"
/* Mutex to control all mutual exclusions */
static DEFINE_MUTEX(uncore_lock);
/* Root of the all uncore sysfs kobjs */
static struct kobject *uncore_root_kobj;
/* uncore instance count */
static int uncore_instance_count;
/* callbacks for actual HW read/write */
static int (*uncore_read)(struct uncore_data *data, unsigned int *min, unsigned int *max);
static int (*uncore_write)(struct uncore_data *data, unsigned int input, unsigned int min_max);
static int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq);
static ssize_t show_min_max_freq_khz(struct uncore_data *data,
char *buf, int min_max)
{
unsigned int min, max;
int ret;
mutex_lock(&uncore_lock);
ret = uncore_read(data, &min, &max);
mutex_unlock(&uncore_lock);
if (ret)
return ret;
if (min_max)
return sprintf(buf, "%u\n", max);
return sprintf(buf, "%u\n", min);
}
static ssize_t store_min_max_freq_khz(struct uncore_data *data,
const char *buf, ssize_t count,
int min_max)
{
unsigned int input;
if (kstrtouint(buf, 10, &input))
return -EINVAL;
mutex_lock(&uncore_lock);
uncore_write(data, input, min_max);
mutex_unlock(&uncore_lock);
return count;
}
static ssize_t show_perf_status_freq_khz(struct uncore_data *data, char *buf)
{
unsigned int freq;
int ret;
mutex_lock(&uncore_lock);
ret = uncore_read_freq(data, &freq);
mutex_unlock(&uncore_lock);
if (ret)
return ret;
return sprintf(buf, "%u\n", freq);
}
#define store_uncore_min_max(name, min_max) \
static ssize_t store_##name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\
\
return store_min_max_freq_khz(data, buf, count, \
min_max); \
}
#define show_uncore_min_max(name, min_max) \
static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, char *buf)\
{ \
struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\
\
return show_min_max_freq_khz(data, buf, min_max); \
}
#define show_uncore_perf_status(name) \
static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, char *buf)\
{ \
struct uncore_data *data = container_of(attr, struct uncore_data, name##_dev_attr);\
\
return show_perf_status_freq_khz(data, buf); \
}
store_uncore_min_max(min_freq_khz, 0);
store_uncore_min_max(max_freq_khz, 1);
show_uncore_min_max(min_freq_khz, 0);
show_uncore_min_max(max_freq_khz, 1);
show_uncore_perf_status(current_freq_khz);
#define show_uncore_data(member_name) \
static ssize_t show_##member_name(struct device *dev, \
struct device_attribute *attr, char *buf)\
{ \
struct uncore_data *data = container_of(attr, struct uncore_data,\
member_name##_dev_attr);\
\
return scnprintf(buf, PAGE_SIZE, "%u\n", \
data->member_name); \
} \
show_uncore_data(initial_min_freq_khz);
show_uncore_data(initial_max_freq_khz);
#define init_attribute_rw(_name) \
do { \
sysfs_attr_init(&data->_name##_dev_attr.attr); \
data->_name##_dev_attr.show = show_##_name; \
data->_name##_dev_attr.store = store_##_name; \
data->_name##_dev_attr.attr.name = #_name; \
data->_name##_dev_attr.attr.mode = 0644; \
} while (0)
#define init_attribute_ro(_name) \
do { \
sysfs_attr_init(&data->_name##_dev_attr.attr); \
data->_name##_dev_attr.show = show_##_name; \
data->_name##_dev_attr.store = NULL; \
data->_name##_dev_attr.attr.name = #_name; \
data->_name##_dev_attr.attr.mode = 0444; \
} while (0)
#define init_attribute_root_ro(_name) \
do { \
sysfs_attr_init(&data->_name##_dev_attr.attr); \
data->_name##_dev_attr.show = show_##_name; \
data->_name##_dev_attr.store = NULL; \
data->_name##_dev_attr.attr.name = #_name; \
data->_name##_dev_attr.attr.mode = 0400; \
} while (0)
static int create_attr_group(struct uncore_data *data, char *name)
{
int ret, index = 0;
init_attribute_rw(max_freq_khz);
init_attribute_rw(min_freq_khz);
init_attribute_ro(initial_min_freq_khz);
init_attribute_ro(initial_max_freq_khz);
init_attribute_root_ro(current_freq_khz);
data->uncore_attrs[index++] = &data->max_freq_khz_dev_attr.attr;
data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr;
data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr;
data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr;
data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr;
data->uncore_attrs[index] = NULL;
data->uncore_attr_group.name = name;
data->uncore_attr_group.attrs = data->uncore_attrs;
ret = sysfs_create_group(uncore_root_kobj, &data->uncore_attr_group);
return ret;
}
static void delete_attr_group(struct uncore_data *data, char *name)
{
sysfs_remove_group(uncore_root_kobj, &data->uncore_attr_group);
}
int uncore_freq_add_entry(struct uncore_data *data, int cpu)
{
int ret = 0;
mutex_lock(&uncore_lock);
if (data->valid) {
/* control cpu changed */
data->control_cpu = cpu;
goto uncore_unlock;
}
sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
uncore_read(data, &data->initial_min_freq_khz, &data->initial_max_freq_khz);
ret = create_attr_group(data, data->name);
if (!ret) {
data->control_cpu = cpu;
data->valid = true;
}
uncore_unlock:
mutex_unlock(&uncore_lock);
return ret;
}
EXPORT_SYMBOL_NS_GPL(uncore_freq_add_entry, INTEL_UNCORE_FREQUENCY);
void uncore_freq_remove_die_entry(struct uncore_data *data)
{
mutex_lock(&uncore_lock);
delete_attr_group(data, data->name);
data->control_cpu = -1;
data->valid = false;
mutex_unlock(&uncore_lock);
}
EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY);
int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max),
int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int set_max),
int (*read_freq)(struct uncore_data *data, unsigned int *freq))
{
mutex_lock(&uncore_lock);
uncore_read = read_control_freq;
uncore_write = write_control_freq;
uncore_read_freq = read_freq;
if (!uncore_root_kobj)
uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency",
&cpu_subsys.dev_root->kobj);
if (uncore_root_kobj)
++uncore_instance_count;
mutex_unlock(&uncore_lock);
return uncore_root_kobj ? 0 : -ENOMEM;
}
EXPORT_SYMBOL_NS_GPL(uncore_freq_common_init, INTEL_UNCORE_FREQUENCY);
void uncore_freq_common_exit(void)
{
mutex_lock(&uncore_lock);
--uncore_instance_count;
if (!uncore_instance_count) {
kobject_put(uncore_root_kobj);
uncore_root_kobj = NULL;
}
mutex_unlock(&uncore_lock);
}
EXPORT_SYMBOL_NS_GPL(uncore_freq_common_exit, INTEL_UNCORE_FREQUENCY);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel Uncore Frequency Common Module");
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Intel Uncore Frequency Control: Common defines and prototypes
* Copyright (c) 2022, Intel Corporation.
* All rights reserved.
*
*/
#ifndef __INTEL_UNCORE_FREQ_COMMON_H
#define __INTEL_UNCORE_FREQ_COMMON_H
#include <linux/device.h>
/**
* struct uncore_data - Encapsulate all uncore data
* @stored_uncore_data: Last user changed MSR 620 value, which will be restored
* on system resume.
* @initial_min_freq_khz: Sampled minimum uncore frequency at driver init
* @initial_max_freq_khz: Sampled maximum uncore frequency at driver init
* @control_cpu: Designated CPU for a die to read/write
* @valid: Mark the data valid/invalid
* @package_id: Package id for this instance
* @die_id: Die id for this instance
* @name: Sysfs entry name for this instance
* @uncore_attr_group: Attribute group storage
* @max_freq_khz_dev_attr: Storage for device attribute max_freq_khz
* @mix_freq_khz_dev_attr: Storage for device attribute min_freq_khz
* @initial_max_freq_khz_dev_attr: Storage for device attribute initial_max_freq_khz
* @initial_min_freq_khz_dev_attr: Storage for device attribute initial_min_freq_khz
* @current_freq_khz_dev_attr: Storage for device attribute current_freq_khz
* @uncore_attrs: Attribute storage for group creation
*
* This structure is used to encapsulate all data related to uncore sysfs
* settings for a die/package.
*/
struct uncore_data {
u64 stored_uncore_data;
u32 initial_min_freq_khz;
u32 initial_max_freq_khz;
int control_cpu;
bool valid;
int package_id;
int die_id;
char name[32];
struct attribute_group uncore_attr_group;
struct device_attribute max_freq_khz_dev_attr;
struct device_attribute min_freq_khz_dev_attr;
struct device_attribute initial_max_freq_khz_dev_attr;
struct device_attribute initial_min_freq_khz_dev_attr;
struct device_attribute current_freq_khz_dev_attr;
struct attribute *uncore_attrs[6];
};
int uncore_freq_common_init(int (*read_control_freq)(struct uncore_data *data, unsigned int *min, unsigned int *max),
int (*write_control_freq)(struct uncore_data *data, unsigned int input, unsigned int min_max),
int (*uncore_read_freq)(struct uncore_data *data, unsigned int *freq));
void uncore_freq_common_exit(void);
int uncore_freq_add_entry(struct uncore_data *data, int cpu);
void uncore_freq_remove_die_entry(struct uncore_data *data);
#endif
...@@ -384,12 +384,9 @@ static acpi_status __init ...@@ -384,12 +384,9 @@ static acpi_status __init
check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv)
{ {
const struct acpi_device_id *ids = context; const struct acpi_device_id *ids = context;
struct acpi_device *dev; struct acpi_device *dev = acpi_fetch_acpi_dev(handle);
if (acpi_bus_get_device(handle, &dev) != 0) if (dev && acpi_match_device_ids(dev, ids) == 0)
return AE_OK;
if (acpi_match_device_ids(dev, ids) == 0)
if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL))) if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL)))
dev_info(&dev->dev, dev_info(&dev->dev,
"intel-vbtn: created platform device\n"); "intel-vbtn: created platform device\n");
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define TABLE_OFFSET_SHIFT 3 #define TABLE_OFFSET_SHIFT 3
static DEFINE_IDA(intel_vsec_ida); static DEFINE_IDA(intel_vsec_ida);
static DEFINE_IDA(intel_vsec_sdsi_ida);
/** /**
* struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers. * struct intel_vsec_header - Common fields of Intel VSEC and DVSEC registers.
...@@ -63,12 +64,14 @@ enum intel_vsec_id { ...@@ -63,12 +64,14 @@ enum intel_vsec_id {
VSEC_ID_TELEMETRY = 2, VSEC_ID_TELEMETRY = 2,
VSEC_ID_WATCHER = 3, VSEC_ID_WATCHER = 3,
VSEC_ID_CRASHLOG = 4, VSEC_ID_CRASHLOG = 4,
VSEC_ID_SDSI = 65,
}; };
static enum intel_vsec_id intel_vsec_allow_list[] = { static enum intel_vsec_id intel_vsec_allow_list[] = {
VSEC_ID_TELEMETRY, VSEC_ID_TELEMETRY,
VSEC_ID_WATCHER, VSEC_ID_WATCHER,
VSEC_ID_CRASHLOG, VSEC_ID_CRASHLOG,
VSEC_ID_SDSI,
}; };
static const char *intel_vsec_name(enum intel_vsec_id id) static const char *intel_vsec_name(enum intel_vsec_id id)
...@@ -83,6 +86,9 @@ static const char *intel_vsec_name(enum intel_vsec_id id) ...@@ -83,6 +86,9 @@ static const char *intel_vsec_name(enum intel_vsec_id id)
case VSEC_ID_CRASHLOG: case VSEC_ID_CRASHLOG:
return "crashlog"; return "crashlog";
case VSEC_ID_SDSI:
return "sdsi";
default: default:
return NULL; return NULL;
} }
...@@ -211,6 +217,10 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he ...@@ -211,6 +217,10 @@ static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *he
intel_vsec_dev->resource = res; intel_vsec_dev->resource = res;
intel_vsec_dev->num_resources = header->num_entries; intel_vsec_dev->num_resources = header->num_entries;
intel_vsec_dev->quirks = quirks; intel_vsec_dev->quirks = quirks;
if (header->id == VSEC_ID_SDSI)
intel_vsec_dev->ida = &intel_vsec_sdsi_ida;
else
intel_vsec_dev->ida = &intel_vsec_ida; intel_vsec_dev->ida = &intel_vsec_ida;
return intel_vsec_add_aux(pdev, intel_vsec_dev, intel_vsec_name(header->id)); return intel_vsec_add_aux(pdev, intel_vsec_dev, intel_vsec_name(header->id));
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <acpi/battery.h>
#define LED_DEVICE(_name, max, flag) struct led_classdev _name = { \ #define LED_DEVICE(_name, max, flag) struct led_classdev _name = { \
.name = __stringify(_name), \ .name = __stringify(_name), \
.max_brightness = max, \ .max_brightness = max, \
...@@ -458,14 +460,14 @@ static ssize_t fn_lock_show(struct device *dev, ...@@ -458,14 +460,14 @@ static ssize_t fn_lock_show(struct device *dev,
return sysfs_emit(buffer, "%d\n", status); return sysfs_emit(buffer, "%d\n", status);
} }
static ssize_t battery_care_limit_store(struct device *dev, static ssize_t charge_control_end_threshold_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buffer, size_t count) const char *buf, size_t count)
{ {
unsigned long value; unsigned long value;
int ret; int ret;
ret = kstrtoul(buffer, 10, &value); ret = kstrtoul(buf, 10, &value);
if (ret) if (ret)
return ret; return ret;
...@@ -486,9 +488,9 @@ static ssize_t battery_care_limit_store(struct device *dev, ...@@ -486,9 +488,9 @@ static ssize_t battery_care_limit_store(struct device *dev,
return -EINVAL; return -EINVAL;
} }
static ssize_t battery_care_limit_show(struct device *dev, static ssize_t charge_control_end_threshold_show(struct device *device,
struct device_attribute *attr, struct device_attribute *attr,
char *buffer) char *buf)
{ {
unsigned int status; unsigned int status;
union acpi_object *r; union acpi_object *r;
...@@ -520,15 +522,52 @@ static ssize_t battery_care_limit_show(struct device *dev, ...@@ -520,15 +522,52 @@ static ssize_t battery_care_limit_show(struct device *dev,
if (status != 80 && status != 100) if (status != 80 && status != 100)
status = 0; status = 0;
return sysfs_emit(buffer, "%d\n", status); return sysfs_emit(buf, "%d\n", status);
}
static ssize_t battery_care_limit_show(struct device *dev,
struct device_attribute *attr,
char *buffer)
{
return charge_control_end_threshold_show(dev, attr, buffer);
}
static ssize_t battery_care_limit_store(struct device *dev,
struct device_attribute *attr,
const char *buffer, size_t count)
{
return charge_control_end_threshold_store(dev, attr, buffer, count);
} }
static DEVICE_ATTR_RW(fan_mode); static DEVICE_ATTR_RW(fan_mode);
static DEVICE_ATTR_RW(usb_charge); static DEVICE_ATTR_RW(usb_charge);
static DEVICE_ATTR_RW(reader_mode); static DEVICE_ATTR_RW(reader_mode);
static DEVICE_ATTR_RW(fn_lock); static DEVICE_ATTR_RW(fn_lock);
static DEVICE_ATTR_RW(charge_control_end_threshold);
static DEVICE_ATTR_RW(battery_care_limit); static DEVICE_ATTR_RW(battery_care_limit);
static int lg_battery_add(struct power_supply *battery)
{
if (device_create_file(&battery->dev,
&dev_attr_charge_control_end_threshold))
return -ENODEV;
return 0;
}
static int lg_battery_remove(struct power_supply *battery)
{
device_remove_file(&battery->dev,
&dev_attr_charge_control_end_threshold);
return 0;
}
static struct acpi_battery_hook battery_hook = {
.add_battery = lg_battery_add,
.remove_battery = lg_battery_remove,
.name = "LG Battery Extension",
};
static struct attribute *dev_attributes[] = { static struct attribute *dev_attributes[] = {
&dev_attr_fan_mode.attr, &dev_attr_fan_mode.attr,
&dev_attr_usb_charge.attr, &dev_attr_usb_charge.attr,
...@@ -711,6 +750,7 @@ static int acpi_add(struct acpi_device *device) ...@@ -711,6 +750,7 @@ static int acpi_add(struct acpi_device *device)
led_classdev_register(&pf_device->dev, &tpad_led); led_classdev_register(&pf_device->dev, &tpad_led);
wmi_input_setup(); wmi_input_setup();
battery_hook_register(&battery_hook);
return 0; return 0;
...@@ -728,6 +768,7 @@ static int acpi_remove(struct acpi_device *device) ...@@ -728,6 +768,7 @@ static int acpi_remove(struct acpi_device *device)
led_classdev_unregister(&tpad_led); led_classdev_unregister(&tpad_led);
led_classdev_unregister(&kbd_backlight); led_classdev_unregister(&kbd_backlight);
battery_hook_unregister(&battery_hook);
wmi_input_destroy(); wmi_input_destroy();
platform_device_unregister(pf_device); platform_device_unregister(pf_device);
pf_device = NULL; pf_device = NULL;
......
This diff is collapsed.
...@@ -62,6 +62,10 @@ struct tlmi_pwd_setting { ...@@ -62,6 +62,10 @@ struct tlmi_pwd_setting {
char kbdlang[TLMI_LANG_MAXLEN]; char kbdlang[TLMI_LANG_MAXLEN];
int index; /*Used for HDD and NVME auth */ int index; /*Used for HDD and NVME auth */
enum level_option level; enum level_option level;
bool cert_installed;
char *certificate;
char *signature;
char *save_signature;
}; };
/* Attribute setting details */ /* Attribute setting details */
...@@ -82,6 +86,7 @@ struct think_lmi { ...@@ -82,6 +86,7 @@ struct think_lmi {
bool pending_changes; bool pending_changes;
bool can_debug_cmd; bool can_debug_cmd;
bool opcode_support; bool opcode_support;
bool certificate_support;
struct tlmi_attr_setting *setting[TLMI_SETTINGS_COUNT]; struct tlmi_attr_setting *setting[TLMI_SETTINGS_COUNT];
struct device *class_dev; struct device *class_dev;
......
This diff is collapsed.
This diff is collapsed.
...@@ -1024,7 +1024,15 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, ...@@ -1024,7 +1024,15 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
u32 val_a, u32 val_b); u32 val_a, u32 val_b);
#ifdef CONFIG_X86
struct acpi_s2idle_dev_ops {
struct list_head list_node;
void (*prepare)(void);
void (*restore)(void);
};
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);
#endif /* CONFIG_X86 */
#ifndef CONFIG_IA64 #ifndef CONFIG_IA64
void arch_reserve_mem_area(acpi_physical_address addr, size_t size); void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
#else #else
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment