Merge tag 'platform-drivers-x86-v5.8-1' of git://git.infradead.org/linux-platform-drivers-x86

Pull x86 platform driver updates from Andy Shevchenko:

 - Add a support of the media keys on the ASUS laptop UX325JA/UX425JA

 - ASUS WMI driver can now handle 2-in-1 models T100TA, T100CHI, T100HA,
   T200TA

 - Big refactoring of Intel SCU driver with Elkhart Lake support has
   been added

 - Slim Bootloarder firmware update signaling WMI driver has been added

 - Thinkpad ACPI driver can handle dual fan configuration on new P and X
   models

 - Touchscreen DMI driver has been extended to support
    - MP-man MPWIN895CL tablet
    - ONDA V891 v5 tablet
    - techBite Arc 11.6
    - Trekstor Twin 10.1
    - Trekstor Yourbook C11B
    - Vinga J116

 - Virtual Button driver got a few fixes to detect mode of 2-in-1 tablet
   models

 - Intel Speed Select tools update

 - Plenty of small cleanups here and there

* tag 'platform-drivers-x86-v5.8-1' of git://git.infradead.org/linux-platform-drivers-x86: (89 commits)
  platform/x86: dcdbas: Check SMBIOS for protected buffer address
  platform/x86: asus_wmi: Reserve more space for struct bias_args
  platform/x86: intel-vbtn: Only blacklist SW_TABLET_MODE on the 9 / "Laptop" chasis-type
  platform/x86: intel-hid: Add a quirk to support HP Spectre X2 (2015)
  platform/x86: touchscreen_dmi: Update Trekstor Twin 10.1 entry
  platform/x86: touchscreen_dmi: Add info for the Trekstor Yourbook C11B
  platform/x86: hp-wmi: Introduce HPWMI_POWER_FW_OR_HW as convenient shortcut
  platform/x86: hp-wmi: Convert simple_strtoul() to kstrtou32()
  platform/x86: hp-wmi: Refactor postcode_store() to follow standard patterns
  platform/x86: acerhdf: replace space by * in modalias
  platform/x86: ISST: Increase timeout
  tools/power/x86/intel-speed-select: Fix invalid core mask
  tools/power/x86/intel-speed-select: Increase CPU count
  tools/power/x86/intel-speed-select: Fix json perf-profile output output
  platform/x86: dell-wmi: Ignore keyboard attached / detached events
  platform/x86: dell-laptop: don't register micmute LED if there is no token
  platform/x86: thinkpad_acpi: Replace custom approach by kstrtoint()
  platform/x86: thinkpad_acpi: Use strndup_user() in dispatch_proc_write()
  platform/x86: thinkpad_acpi: Replace next_cmd(&buf) with strsep(&buf, ",")
  platform/x86: intel-vbtn: Detect switch position before registering the input-device
  ...
This commit is contained in:
Linus Torvalds
2020-06-02 12:56:58 -07:00
63 changed files with 2331 additions and 1708 deletions

View File

@@ -0,0 +1,22 @@
These files allow sending arbitrary IPC commands to the PMC/SCU which
may be dangerous. These will be removed eventually and should not be
used in any new applications.
What: /sys/bus/platform/devices/INT34D2:00/simplecmd
Date: Jun 2015
KernelVersion: 4.1
Contact: Mika Westerberg <mika.westerberg@linux.intel.com>
Description: This interface allows userspace to send an arbitrary
IPC command to the PMC/SCU.
Format: %d %d where first number is command and
second number is subcommand.
What: /sys/bus/platform/devices/INT34D2:00/northpeak
Date: Jun 2015
KernelVersion: 4.1
Contact: Mika Westerberg <mika.westerberg@linux.intel.com>
Description: This interface allows userspace to enable and disable
Northpeak through the PMC/SCU.
Format: %u.

View File

@@ -0,0 +1,12 @@
What: /sys/bus/wmi/devices/44FADEB1-B204-40F2-8581-394BBDC1B651/firmware_update_request
Date: April 2020
KernelVersion: 5.7
Contact: "Jithu Joseph" <jithu.joseph@intel.com>
Description:
Allow user space entities to trigger update of Slim
Bootloader (SBL). This attribute normally has a value
of 0 and userspace can signal SBL to update firmware,
on next reboot, by writing a value of 1.
There are two available states:
* 0 -> Skip firmware update while rebooting
* 1 -> Attempt firmware update on next reboot

View File

@@ -8529,6 +8529,13 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel_atomisp2_pm.c
INTEL BROXTON PMC DRIVER
M: Mika Westerberg <mika.westerberg@linux.intel.com>
M: Zha Qipeng <qipeng.zha@intel.com>
S: Maintained
F: drivers/mfd/intel_pmc_bxt.c
F: include/linux/mfd/intel_pmc_bxt.h
INTEL C600 SERIES SAS CONTROLLER DRIVER
M: Intel SCU Linux support <intel-linux-scu@intel.com>
M: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
@@ -8736,6 +8743,13 @@ F: include/uapi/linux/mic_common.h
F: include/uapi/linux/mic_ioctl.h
F: include/uapi/linux/scif_ioctl.h
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
INTEL PMC CORE DRIVER
M: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
M: Vishwanath Somayaji <vishwanath.somayaji@intel.com>
@@ -8743,15 +8757,6 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/intel_pmc_core*
INTEL PMC/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_pmc_ipc.h
F: arch/x86/include/asm/intel_punit_ipc.h
F: drivers/platform/x86/intel_pmc_ipc.c
F: drivers/platform/x86/intel_punit_ipc.c
INTEL PMIC GPIO DRIVERS
M: Andy Shevchenko <andy@kernel.org>
S: Maintained
@@ -8790,6 +8795,12 @@ S: Supported
F: drivers/infiniband/hw/i40iw/
F: include/uapi/rdma/i40iw-abi.h
INTEL SCU DRIVERS
M: Mika Westerberg <mika.westerberg@linux.intel.com>
S: Maintained
F: arch/x86/include/asm/intel_scu_ipc.h
F: drivers/platform/x86/intel_scu_*
INTEL SPEED SELECT TECHNOLOGY
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
L: platform-driver-x86@vger.kernel.org
@@ -8856,6 +8867,13 @@ F: Documentation/admin-guide/wimax/i2400m.rst
F: drivers/net/wimax/i2400m/
F: include/uapi/linux/wimax/i2400m.h
INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER
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
INTEL WMI THUNDERBOLT FORCE POWER DRIVER
M: Mario Limonciello <mario.limonciello@dell.com>
S: Maintained

View File

@@ -597,7 +597,7 @@ config X86_INTEL_MID
select I2C
select DW_APB_TIMER
select APB_TIMER
select INTEL_SCU_IPC
select INTEL_SCU_PCI
select MFD_INTEL_MSIC
---help---
Select to build a kernel capable of supporting Intel MID (Mobile

View File

@@ -88,11 +88,17 @@ static inline bool intel_mid_has_msic(void)
return (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL);
}
extern void intel_scu_devices_create(void);
extern void intel_scu_devices_destroy(void);
#else /* !CONFIG_X86_INTEL_MID */
#define intel_mid_identify_cpu() 0
#define intel_mid_has_msic() 0
static inline void intel_scu_devices_create(void) { }
static inline void intel_scu_devices_destroy(void) { }
#endif /* !CONFIG_X86_INTEL_MID */
enum intel_mid_timer_options {
@@ -115,9 +121,6 @@ extern enum intel_mid_timer_options intel_mid_timer_options;
#define SFI_MTMR_MAX_NUM 8
#define SFI_MRTC_MAX 8
extern void intel_scu_devices_create(void);
extern void intel_scu_devices_destroy(void);
/* VRTC timer */
#define MRST_VRTC_MAP_SZ 1024
/* #define MRST_VRTC_PGOFFSET 0xc00 */

View File

@@ -1,59 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_INTEL_PMC_IPC_H_
#define _ASM_X86_INTEL_PMC_IPC_H_
/* Commands */
#define PMC_IPC_PMIC_ACCESS 0xFF
#define PMC_IPC_PMIC_ACCESS_READ 0x0
#define PMC_IPC_PMIC_ACCESS_WRITE 0x1
#define PMC_IPC_USB_PWR_CTRL 0xF0
#define PMC_IPC_PMIC_BLACKLIST_SEL 0xEF
#define PMC_IPC_PHY_CONFIG 0xEE
#define PMC_IPC_NORTHPEAK_CTRL 0xED
#define PMC_IPC_PM_DEBUG 0xEC
#define PMC_IPC_PMC_TELEMTRY 0xEB
#define PMC_IPC_PMC_FW_MSG_CTRL 0xEA
/* IPC return code */
#define IPC_ERR_NONE 0
#define IPC_ERR_CMD_NOT_SUPPORTED 1
#define IPC_ERR_CMD_NOT_SERVICED 2
#define IPC_ERR_UNABLE_TO_SERVICE 3
#define IPC_ERR_CMD_INVALID 4
#define IPC_ERR_CMD_FAILED 5
#define IPC_ERR_EMSECURITY 6
#define IPC_ERR_UNSIGNEDKERNEL 7
/* GCR reg offsets from gcr base*/
#define PMC_GCR_PMC_CFG_REG 0x08
#define PMC_GCR_TELEM_DEEP_S0IX_REG 0x78
#define PMC_GCR_TELEM_SHLW_S0IX_REG 0x80
#if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
u32 *out, u32 outlen);
int intel_pmc_s0ix_counter_read(u64 *data);
int intel_pmc_gcr_read64(u32 offset, u64 *data);
#else
static inline int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
u32 *out, u32 outlen)
{
return -EINVAL;
}
static inline int intel_pmc_s0ix_counter_read(u64 *data)
{
return -EINVAL;
}
static inline int intel_pmc_gcr_read64(u32 offset, u64 *data)
{
return -EINVAL;
}
#endif /*CONFIG_INTEL_PMC_IPC*/
#endif

View File

@@ -2,61 +2,69 @@
#ifndef _ASM_X86_INTEL_SCU_IPC_H_
#define _ASM_X86_INTEL_SCU_IPC_H_
#include <linux/notifier.h>
#include <linux/ioport.h>
#define IPCMSG_INDIRECT_READ 0x02
#define IPCMSG_INDIRECT_WRITE 0x05
struct device;
struct intel_scu_ipc_dev;
#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */
/**
* struct intel_scu_ipc_data - Data used to configure SCU IPC
* @mem: Base address of SCU IPC MMIO registers
* @irq: The IRQ number used for SCU (optional)
*/
struct intel_scu_ipc_data {
struct resource mem;
int irq;
};
#define IPCMSG_WARM_RESET 0xF0
#define IPCMSG_COLD_RESET 0xF1
#define IPCMSG_SOFT_RESET 0xF2
#define IPCMSG_COLD_BOOT 0xF3
struct intel_scu_ipc_dev *
__intel_scu_ipc_register(struct device *parent,
const struct intel_scu_ipc_data *scu_data,
struct module *owner);
#define IPCMSG_VRTC 0xFA /* Set vRTC device */
/* Command id associated with message IPCMSG_VRTC */
#define IPC_CMD_VRTC_SETTIME 1 /* Set time */
#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */
#define intel_scu_ipc_register(parent, scu_data) \
__intel_scu_ipc_register(parent, scu_data, THIS_MODULE)
/* Read single register */
int intel_scu_ipc_ioread8(u16 addr, u8 *data);
void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu);
/* Read a vector */
int intel_scu_ipc_readv(u16 *addr, u8 *data, int len);
struct intel_scu_ipc_dev *
__devm_intel_scu_ipc_register(struct device *parent,
const struct intel_scu_ipc_data *scu_data,
struct module *owner);
/* Write single register */
int intel_scu_ipc_iowrite8(u16 addr, u8 data);
#define devm_intel_scu_ipc_register(parent, scu_data) \
__devm_intel_scu_ipc_register(parent, scu_data, THIS_MODULE)
/* Write a vector */
int intel_scu_ipc_writev(u16 *addr, u8 *data, int len);
struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void);
void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu);
struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev);
/* Update single register based on the mask */
int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);
int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr,
u8 *data);
int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr,
u8 data);
int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr,
u8 *data, size_t len);
int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr,
u8 *data, size_t len);
/* Issue commands to the SCU with or without data */
int intel_scu_ipc_simple_command(int cmd, int sub);
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
u32 *out, int outlen);
int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr,
u8 data, u8 mask);
extern struct blocking_notifier_head intel_scu_notifier;
int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd,
int sub);
int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd,
int sub, const void *in, size_t inlen,
size_t size, void *out, size_t outlen);
static inline void intel_scu_notifier_add(struct notifier_block *nb)
static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int cmd,
int sub, const void *in, size_t inlen,
void *out, size_t outlen)
{
blocking_notifier_chain_register(&intel_scu_notifier, nb);
return intel_scu_ipc_dev_command_with_size(scu, cmd, sub, in, inlen,
inlen, out, outlen);
}
static inline void intel_scu_notifier_remove(struct notifier_block *nb)
{
blocking_notifier_chain_unregister(&intel_scu_notifier, nb);
}
static inline int intel_scu_notifier_post(unsigned long v, void *p)
{
return blocking_notifier_call_chain(&intel_scu_notifier, v, p);
}
#define SCU_AVAILABLE 1
#define SCU_DOWN 2
#include <asm/intel_scu_ipc_legacy.h>
#endif

View File

@@ -0,0 +1,91 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_INTEL_SCU_IPC_LEGACY_H_
#define _ASM_X86_INTEL_SCU_IPC_LEGACY_H_
#include <linux/notifier.h>
#define IPCMSG_INDIRECT_READ 0x02
#define IPCMSG_INDIRECT_WRITE 0x05
#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */
#define IPCMSG_WARM_RESET 0xF0
#define IPCMSG_COLD_RESET 0xF1
#define IPCMSG_SOFT_RESET 0xF2
#define IPCMSG_COLD_BOOT 0xF3
#define IPCMSG_VRTC 0xFA /* Set vRTC device */
/* Command id associated with message IPCMSG_VRTC */
#define IPC_CMD_VRTC_SETTIME 1 /* Set time */
#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */
/* Don't call these in new code - they will be removed eventually */
/* Read single register */
static inline int intel_scu_ipc_ioread8(u16 addr, u8 *data)
{
return intel_scu_ipc_dev_ioread8(NULL, addr, data);
}
/* Read a vector */
static inline int intel_scu_ipc_readv(u16 *addr, u8 *data, int len)
{
return intel_scu_ipc_dev_readv(NULL, addr, data, len);
}
/* Write single register */
static inline int intel_scu_ipc_iowrite8(u16 addr, u8 data)
{
return intel_scu_ipc_dev_iowrite8(NULL, addr, data);
}
/* Write a vector */
static inline int intel_scu_ipc_writev(u16 *addr, u8 *data, int len)
{
return intel_scu_ipc_dev_writev(NULL, addr, data, len);
}
/* Update single register based on the mask */
static inline int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask)
{
return intel_scu_ipc_dev_update(NULL, addr, data, mask);
}
/* Issue commands to the SCU with or without data */
static inline int intel_scu_ipc_simple_command(int cmd, int sub)
{
return intel_scu_ipc_dev_simple_command(NULL, cmd, sub);
}
static inline int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
u32 *out, int outlen)
{
/* New API takes both inlen and outlen as bytes so convert here */
size_t inbytes = inlen * sizeof(u32);
size_t outbytes = outlen * sizeof(u32);
return intel_scu_ipc_dev_command_with_size(NULL, cmd, sub, in, inbytes,
inlen, out, outbytes);
}
extern struct blocking_notifier_head intel_scu_notifier;
static inline void intel_scu_notifier_add(struct notifier_block *nb)
{
blocking_notifier_chain_register(&intel_scu_notifier, nb);
}
static inline void intel_scu_notifier_remove(struct notifier_block *nb)
{
blocking_notifier_chain_unregister(&intel_scu_notifier, nb);
}
static inline int intel_scu_notifier_post(unsigned long v, void *p)
{
return blocking_notifier_call_chain(&intel_scu_notifier, v, p);
}
#define SCU_AVAILABLE 1
#define SCU_DOWN 2
#endif

View File

@@ -10,6 +10,8 @@
#define TELEM_MAX_EVENTS_SRAM 28
#define TELEM_MAX_OS_ALLOCATED_EVENTS 20
#include <asm/intel_scu_ipc.h>
enum telemetry_unit {
TELEM_PSS = 0,
TELEM_IOSS,
@@ -51,6 +53,8 @@ struct telemetry_plt_config {
struct telemetry_unit_config ioss_config;
struct mutex telem_trace_lock;
struct mutex telem_lock;
struct intel_pmc_dev *pmc;
struct intel_scu_ipc_dev *scu;
bool telem_in_use;
};
@@ -92,7 +96,7 @@ int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
int telemetry_clear_pltdata(void);
int telemetry_pltconfig_valid(void);
struct telemetry_plt_config *telemetry_get_pltdata(void);
int telemetry_get_evtname(enum telemetry_unit telem_unit,
const char **name, int len);

View File

@@ -3915,6 +3915,7 @@ void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
else
dev->fwnode = fwnode;
}
EXPORT_SYMBOL_GPL(set_secondary_fwnode);
/**
* device_set_of_node_from_dev - reuse device-tree node of another device

View File

@@ -726,6 +726,54 @@ void software_node_unregister_nodes(const struct software_node *nodes)
}
EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
/**
* software_node_register_node_group - Register a group of software nodes
* @node_group: NULL terminated array of software node pointers to be registered
*
* Register multiple software nodes at once.
*/
int software_node_register_node_group(const struct software_node **node_group)
{
unsigned int i;
int ret;
if (!node_group)
return 0;
for (i = 0; node_group[i]; i++) {
ret = software_node_register(node_group[i]);
if (ret) {
software_node_unregister_node_group(node_group);
return ret;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(software_node_register_node_group);
/**
* software_node_unregister_node_group - Unregister a group of software nodes
* @node_group: NULL terminated array of software node pointers to be unregistered
*
* Unregister multiple software nodes at once.
*/
void software_node_unregister_node_group(const struct software_node **node_group)
{
struct swnode *swnode;
unsigned int i;
if (!node_group)
return;
for (i = 0; node_group[i]; i++) {
swnode = software_node_to_swnode(node_group[i]);
if (swnode)
fwnode_remove_software_node(&swnode->fwnode);
}
}
EXPORT_SYMBOL_GPL(software_node_unregister_node_group);
/**
* software_node_register - Register static software node
* @node: The software node to be registered

View File

@@ -566,7 +566,7 @@ config INTEL_SOC_PMIC
config INTEL_SOC_PMIC_BXTWC
tristate "Support for Intel Broxton Whiskey Cove PMIC"
depends on INTEL_PMC_IPC
depends on MFD_INTEL_PMC_BXT
select MFD_CORE
select REGMAP_IRQ
help
@@ -608,7 +608,7 @@ config INTEL_SOC_PMIC_MRFLD
tristate "Support for Intel Merrifield Basin Cove PMIC"
depends on GPIOLIB
depends on ACPI
depends on INTEL_SCU_IPC
depends on INTEL_SCU
select MFD_CORE
select REGMAP_IRQ
help
@@ -640,13 +640,27 @@ config MFD_INTEL_LPSS_PCI
config MFD_INTEL_MSIC
bool "Intel MSIC"
depends on INTEL_SCU_IPC
depends on INTEL_SCU
select MFD_CORE
help
Select this option to enable access to Intel MSIC (Avatele
Passage) chip. This chip embeds audio, battery, GPIO, etc.
devices used in Intel Medfield platforms.
config MFD_INTEL_PMC_BXT
tristate "Intel PMC Driver for Broxton"
depends on X86
depends on X86_PLATFORM_DEVICES
depends on ACPI
select INTEL_SCU_IPC
select MFD_CORE
help
This driver provides support for the PMC (Power Management
Controller) on Intel Broxton and Apollo Lake. The PMC is a
multi-function device that exposes IPC, General Control
Register and P-unit access. In addition this creates devices
for iTCO watchdog and telemetry that are part of the PMC.
config MFD_IPAQ_MICRO
bool "Atmel Micro ASIC (iPAQ h3100/h3600/h3700) Support"
depends on SA1100_H3100 || SA1100_H3600

View File

@@ -213,6 +213,7 @@ obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o
obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_INTEL_PMC_BXT) += intel_pmc_bxt.o
obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o

468
drivers/mfd/intel_pmc_bxt.c Normal file
View File

@@ -0,0 +1,468 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the Intel Broxton PMC
*
* (C) Copyright 2014 - 2020 Intel Corporation
*
* This driver is based on Intel SCU IPC driver (intel_scu_ipc.c) by
* Sreedhara DS <sreedhara.ds@intel.com>
*
* The PMC (Power Management Controller) running on the ARC processor
* communicates with another entity running in the IA (Intel Architecture)
* core through an IPC (Intel Processor Communications) mechanism which in
* turn sends messages between the IA and the PMC.
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/mfd/core.h>
#include <linux/mfd/intel_pmc_bxt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_data/itco_wdt.h>
#include <asm/intel_scu_ipc.h>
/* Residency with clock rate at 19.2MHz to usecs */
#define S0IX_RESIDENCY_IN_USECS(d, s) \
({ \
u64 result = 10ull * ((d) + (s)); \
do_div(result, 192); \
result; \
})
/* Resources exported from IFWI */
#define PLAT_RESOURCE_IPC_INDEX 0
#define PLAT_RESOURCE_IPC_SIZE 0x1000
#define PLAT_RESOURCE_GCR_OFFSET 0x1000
#define PLAT_RESOURCE_GCR_SIZE 0x1000
#define PLAT_RESOURCE_BIOS_DATA_INDEX 1
#define PLAT_RESOURCE_BIOS_IFACE_INDEX 2
#define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3
#define PLAT_RESOURCE_ISP_DATA_INDEX 4
#define PLAT_RESOURCE_ISP_IFACE_INDEX 5
#define PLAT_RESOURCE_GTD_DATA_INDEX 6
#define PLAT_RESOURCE_GTD_IFACE_INDEX 7
#define PLAT_RESOURCE_ACPI_IO_INDEX 0
/*
* BIOS does not create an ACPI device for each PMC function, but
* exports multiple resources from one ACPI device (IPC) for multiple
* functions. This driver is responsible for creating a child device and
* to export resources for those functions.
*/
#define SMI_EN_OFFSET 0x0040
#define SMI_EN_SIZE 4
#define TCO_BASE_OFFSET 0x0060
#define TCO_REGS_SIZE 16
#define TELEM_SSRAM_SIZE 240
#define TELEM_PMC_SSRAM_OFFSET 0x1b00
#define TELEM_PUNIT_SSRAM_OFFSET 0x1a00
/* Commands */
#define PMC_NORTHPEAK_CTRL 0xed
static inline bool is_gcr_valid(u32 offset)
{
return offset < PLAT_RESOURCE_GCR_SIZE - 8;
}
/**
* intel_pmc_gcr_read64() - Read a 64-bit PMC GCR register
* @pmc: PMC device pointer
* @offset: offset of GCR register from GCR address base
* @data: data pointer for storing the register output
*
* Reads the 64-bit PMC GCR register at given offset.
*
* Return: Negative value on error or 0 on success.
*/
int intel_pmc_gcr_read64(struct intel_pmc_dev *pmc, u32 offset, u64 *data)
{
if (!is_gcr_valid(offset))
return -EINVAL;
spin_lock(&pmc->gcr_lock);
*data = readq(pmc->gcr_mem_base + offset);
spin_unlock(&pmc->gcr_lock);
return 0;
}
EXPORT_SYMBOL_GPL(intel_pmc_gcr_read64);
/**
* intel_pmc_gcr_update() - Update PMC GCR register bits
* @pmc: PMC device pointer
* @offset: offset of GCR register from GCR address base
* @mask: bit mask for update operation
* @val: update value
*
* Updates the bits of given GCR register as specified by
* @mask and @val.
*
* Return: Negative value on error or 0 on success.
*/
int intel_pmc_gcr_update(struct intel_pmc_dev *pmc, u32 offset, u32 mask, u32 val)
{
u32 new_val;
if (!is_gcr_valid(offset))
return -EINVAL;
spin_lock(&pmc->gcr_lock);
new_val = readl(pmc->gcr_mem_base + offset);
new_val = (new_val & ~mask) | (val & mask);
writel(new_val, pmc->gcr_mem_base + offset);
new_val = readl(pmc->gcr_mem_base + offset);
spin_unlock(&pmc->gcr_lock);
/* Check whether the bit update is successful */
return (new_val & mask) != (val & mask) ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(intel_pmc_gcr_update);
/**
* intel_pmc_s0ix_counter_read() - Read S0ix residency
* @pmc: PMC device pointer
* @data: Out param that contains current S0ix residency count.
*
* Writes to @data how many usecs the system has been in low-power S0ix
* state.
*
* Return: An error code or 0 on success.
*/
int intel_pmc_s0ix_counter_read(struct intel_pmc_dev *pmc, u64 *data)
{
u64 deep, shlw;
spin_lock(&pmc->gcr_lock);
deep = readq(pmc->gcr_mem_base + PMC_GCR_TELEM_DEEP_S0IX_REG);
shlw = readq(pmc->gcr_mem_base + PMC_GCR_TELEM_SHLW_S0IX_REG);
spin_unlock(&pmc->gcr_lock);
*data = S0IX_RESIDENCY_IN_USECS(deep, shlw);
return 0;
}
EXPORT_SYMBOL_GPL(intel_pmc_s0ix_counter_read);
/**
* simplecmd_store() - Send a simple IPC command
* @dev: Device under the attribute is
* @attr: Attribute in question
* @buf: Buffer holding data to be stored to the attribute
* @count: Number of bytes in @buf
*
* Expects a string with two integers separated with space. These two
* values hold command and subcommand that is send to PMC.
*
* Return: Number number of bytes written (@count) or negative errno in
* case of error.
*/
static ssize_t simplecmd_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct intel_pmc_dev *pmc = dev_get_drvdata(dev);
struct intel_scu_ipc_dev *scu = pmc->scu;
int subcmd;
int cmd;
int ret;
ret = sscanf(buf, "%d %d", &cmd, &subcmd);
if (ret != 2) {
dev_err(dev, "Invalid values, expected: cmd subcmd\n");
return -EINVAL;
}
ret = intel_scu_ipc_dev_simple_command(scu, cmd, subcmd);
if (ret)
return ret;
return count;
}
static DEVICE_ATTR_WO(simplecmd);
/**
* northpeak_store() - Enable or disable Northpeak
* @dev: Device under the attribute is
* @attr: Attribute in question
* @buf: Buffer holding data to be stored to the attribute
* @count: Number of bytes in @buf
*
* Expects an unsigned integer. Non-zero enables Northpeak and zero
* disables it.
*
* Return: Number number of bytes written (@count) or negative errno in
* case of error.
*/
static ssize_t northpeak_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct intel_pmc_dev *pmc = dev_get_drvdata(dev);
struct intel_scu_ipc_dev *scu = pmc->scu;
unsigned long val;
int subcmd;
int ret;
ret = kstrtoul(buf, 0, &val);
if (ret)
return ret;
/* Northpeak is enabled if subcmd == 1 and disabled if it is 0 */
if (val)
subcmd = 1;
else
subcmd = 0;
ret = intel_scu_ipc_dev_simple_command(scu, PMC_NORTHPEAK_CTRL, subcmd);
if (ret)
return ret;
return count;
}
static DEVICE_ATTR_WO(northpeak);
static struct attribute *intel_pmc_attrs[] = {
&dev_attr_northpeak.attr,
&dev_attr_simplecmd.attr,
NULL
};
static const struct attribute_group intel_pmc_group = {
.attrs = intel_pmc_attrs,
};
static const struct attribute_group *intel_pmc_groups[] = {
&intel_pmc_group,
NULL
};
static struct resource punit_res[6];
static struct mfd_cell punit = {
.name = "intel_punit_ipc",
.resources = punit_res,
};
static struct itco_wdt_platform_data tco_pdata = {
.name = "Apollo Lake SoC",
.version = 5,
.no_reboot_use_pmc = true,
};
static struct resource tco_res[2];
static const struct mfd_cell tco = {
.name = "iTCO_wdt",
.ignore_resource_conflicts = true,
.resources = tco_res,
.num_resources = ARRAY_SIZE(tco_res),
.platform_data = &tco_pdata,
.pdata_size = sizeof(tco_pdata),
};
static const struct resource telem_res[] = {
DEFINE_RES_MEM(TELEM_PUNIT_SSRAM_OFFSET, TELEM_SSRAM_SIZE),
DEFINE_RES_MEM(TELEM_PMC_SSRAM_OFFSET, TELEM_SSRAM_SIZE),
};
static const struct mfd_cell telem = {
.name = "intel_telemetry",
.resources = telem_res,
.num_resources = ARRAY_SIZE(telem_res),
};
static int intel_pmc_get_tco_resources(struct platform_device *pdev)
{
struct resource *res;
if (acpi_has_watchdog())
return 0;
res = platform_get_resource(pdev, IORESOURCE_IO,
PLAT_RESOURCE_ACPI_IO_INDEX);
if (!res) {
dev_err(&pdev->dev, "Failed to get IO resource\n");
return -EINVAL;
}
tco_res[0].flags = IORESOURCE_IO;
tco_res[0].start = res->start + TCO_BASE_OFFSET;
tco_res[0].end = tco_res[0].start + TCO_REGS_SIZE - 1;
tco_res[1].flags = IORESOURCE_IO;
tco_res[1].start = res->start + SMI_EN_OFFSET;
tco_res[1].end = tco_res[1].start + SMI_EN_SIZE - 1;
return 0;
}
static int intel_pmc_get_resources(struct platform_device *pdev,
struct intel_pmc_dev *pmc,
struct intel_scu_ipc_data *scu_data)
{
struct resource gcr_res;
size_t npunit_res = 0;
struct resource *res;
int ret;
scu_data->irq = platform_get_irq_optional(pdev, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_IPC_INDEX);
if (!res) {
dev_err(&pdev->dev, "Failed to get IPC resource\n");
return -EINVAL;
}
/* IPC registers */
scu_data->mem.flags = res->flags;
scu_data->mem.start = res->start;
scu_data->mem.end = res->start + PLAT_RESOURCE_IPC_SIZE - 1;
/* GCR registers */
gcr_res.flags = res->flags;
gcr_res.start = res->start + PLAT_RESOURCE_GCR_OFFSET;
gcr_res.end = gcr_res.start + PLAT_RESOURCE_GCR_SIZE - 1;
pmc->gcr_mem_base = devm_ioremap_resource(&pdev->dev, &gcr_res);
if (IS_ERR(pmc->gcr_mem_base))
return PTR_ERR(pmc->gcr_mem_base);
/* Only register iTCO watchdog if there is no WDAT ACPI table */
ret = intel_pmc_get_tco_resources(pdev);
if (ret)
return ret;
/* BIOS data register */
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_BIOS_DATA_INDEX);
if (!res) {
dev_err(&pdev->dev, "Failed to get resource of P-unit BIOS data\n");
return -EINVAL;
}
punit_res[npunit_res++] = *res;
/* BIOS interface register */
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_BIOS_IFACE_INDEX);
if (!res) {
dev_err(&pdev->dev, "Failed to get resource of P-unit BIOS interface\n");
return -EINVAL;
}
punit_res[npunit_res++] = *res;
/* ISP data register, optional */
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_ISP_DATA_INDEX);
if (res)
punit_res[npunit_res++] = *res;
/* ISP interface register, optional */
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_ISP_IFACE_INDEX);
if (res)
punit_res[npunit_res++] = *res;
/* GTD data register, optional */
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_GTD_DATA_INDEX);
if (res)
punit_res[npunit_res++] = *res;
/* GTD interface register, optional */
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_GTD_IFACE_INDEX);
if (res)
punit_res[npunit_res++] = *res;
punit.num_resources = npunit_res;
/* Telemetry SSRAM is optional */
res = platform_get_resource(pdev, IORESOURCE_MEM,
PLAT_RESOURCE_TELEM_SSRAM_INDEX);
if (res)
pmc->telem_base = res;
return 0;
}
static int intel_pmc_create_devices(struct intel_pmc_dev *pmc)
{
int ret;
if (!acpi_has_watchdog()) {
ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO, &tco,
1, NULL, 0, NULL);
if (ret)
return ret;
}
ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO, &punit, 1,
NULL, 0, NULL);
if (ret)
return ret;
if (pmc->telem_base) {
ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO,
&telem, 1, pmc->telem_base, 0, NULL);
}
return ret;
}
static const struct acpi_device_id intel_pmc_acpi_ids[] = {
{ "INT34D2" },
{ }
};
MODULE_DEVICE_TABLE(acpi, intel_pmc_acpi_ids);
static int intel_pmc_probe(struct platform_device *pdev)
{
struct intel_scu_ipc_data scu_data = {};
struct intel_pmc_dev *pmc;
int ret;
pmc = devm_kzalloc(&pdev->dev, sizeof(*pmc), GFP_KERNEL);
if (!pmc)
return -ENOMEM;
pmc->dev = &pdev->dev;
spin_lock_init(&pmc->gcr_lock);
ret = intel_pmc_get_resources(pdev, pmc, &scu_data);
if (ret) {
dev_err(&pdev->dev, "Failed to request resources\n");
return ret;
}
pmc->scu = devm_intel_scu_ipc_register(&pdev->dev, &scu_data);
if (IS_ERR(pmc->scu))
return PTR_ERR(pmc->scu);
platform_set_drvdata(pdev, pmc);
ret = intel_pmc_create_devices(pmc);
if (ret)
dev_err(&pdev->dev, "Failed to create PMC devices\n");
return ret;
}
static struct platform_driver intel_pmc_driver = {
.probe = intel_pmc_probe,
.driver = {
.name = "intel_pmc_bxt",
.acpi_match_table = intel_pmc_acpi_ids,
.dev_groups = intel_pmc_groups,
},
};
module_platform_driver(intel_pmc_driver);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>");
MODULE_DESCRIPTION("Intel Broxton PMC driver");
MODULE_LICENSE("GPL v2");

View File

@@ -15,7 +15,7 @@
#include <linux/mfd/intel_soc_pmic_bxtwc.h>
#include <linux/module.h>
#include <asm/intel_pmc_ipc.h>
#include <asm/intel_scu_ipc.h>
/* PMIC device registers */
#define REG_ADDR_MASK 0xFF00
@@ -58,6 +58,10 @@
/* Whiskey Cove PMIC share same ACPI ID between different platforms */
#define BROXTON_PMIC_WC_HRV 4
#define PMC_PMIC_ACCESS 0xFF
#define PMC_PMIC_READ 0x0
#define PMC_PMIC_WRITE 0x1
enum bxtwc_irqs {
BXTWC_PWRBTN_LVL1_IRQ = 0,
BXTWC_TMU_LVL1_IRQ,
@@ -288,13 +292,12 @@ static int regmap_ipc_byte_reg_read(void *context, unsigned int reg,
ipc_in[0] = reg;
ipc_in[1] = i2c_addr;
ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
PMC_IPC_PMIC_ACCESS_READ,
ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1);
if (ret) {
dev_err(pmic->dev, "Failed to read from PMIC\n");
ret = intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS,
PMC_PMIC_READ, ipc_in, sizeof(ipc_in),
ipc_out, sizeof(ipc_out));
if (ret)
return ret;
}
*val = ipc_out[0];
return 0;
@@ -303,7 +306,6 @@ static int regmap_ipc_byte_reg_read(void *context, unsigned int reg,
static int regmap_ipc_byte_reg_write(void *context, unsigned int reg,
unsigned int val)
{
int ret;
int i2c_addr;
u8 ipc_in[3];
struct intel_soc_pmic *pmic = context;
@@ -321,15 +323,9 @@ static int regmap_ipc_byte_reg_write(void *context, unsigned int reg,
ipc_in[0] = reg;
ipc_in[1] = i2c_addr;
ipc_in[2] = val;
ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
PMC_IPC_PMIC_ACCESS_WRITE,
ipc_in, sizeof(ipc_in), NULL, 0);
if (ret) {
dev_err(pmic->dev, "Failed to write to PMIC\n");
return ret;
}
return 0;
return intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS,
PMC_PMIC_WRITE, ipc_in, sizeof(ipc_in),
NULL, 0);
}
/* sysfs interfaces to r/w PMIC registers, required by initial script */
@@ -457,6 +453,10 @@ static int bxtwc_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, pmic);
pmic->dev = &pdev->dev;
pmic->scu = devm_intel_scu_ipc_dev_get(&pdev->dev);
if (!pmic->scu)
return -EPROBE_DEFER;
pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic,
&bxtwc_regmap_config);
if (IS_ERR(pmic->regmap)) {

View File

@@ -74,10 +74,11 @@ static const struct mfd_cell bcove_dev[] = {
static int bcove_ipc_byte_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct intel_soc_pmic *pmic = context;
u8 ipc_out;
int ret;
ret = intel_scu_ipc_ioread8(reg, &ipc_out);
ret = intel_scu_ipc_dev_ioread8(pmic->scu, reg, &ipc_out);
if (ret)
return ret;
@@ -88,10 +89,11 @@ static int bcove_ipc_byte_reg_read(void *context, unsigned int reg,
static int bcove_ipc_byte_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct intel_soc_pmic *pmic = context;
u8 ipc_in = val;
int ret;
ret = intel_scu_ipc_iowrite8(reg, ipc_in);
ret = intel_scu_ipc_dev_iowrite8(pmic->scu, reg, ipc_in);
if (ret)
return ret;
@@ -117,6 +119,10 @@ static int bcove_probe(struct platform_device *pdev)
if (!pmic)
return -ENOMEM;
pmic->scu = devm_intel_scu_ipc_dev_get(dev);
if (!pmic->scu)
return -ENOMEM;
platform_set_drvdata(pdev, pmic);
pmic->dev = &pdev->dev;

View File

@@ -78,6 +78,16 @@ config HUAWEI_WMI
To compile this driver as a module, choose M here: the module
will be called huawei-wmi.
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
@@ -1269,7 +1279,8 @@ config INTEL_UNCORE_FREQ_CONTROL
config INTEL_BXTWC_PMIC_TMU
tristate "Intel BXT Whiskey Cove TMU Driver"
depends on REGMAP
depends on INTEL_SOC_PMIC_BXTWC && INTEL_PMC_IPC
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
@@ -1295,7 +1306,7 @@ config INTEL_MFLD_THERMAL
config INTEL_MID_POWER_BUTTON
tristate "power button driver for Intel MID platforms"
depends on INTEL_SCU_IPC && INPUT
depends on INTEL_SCU && INPUT
help
This driver handles the power button on the Intel MID platforms.
@@ -1327,14 +1338,6 @@ config INTEL_PMC_CORE
- LTR Ignore
- MPHY/PLL gating status (Sunrisepoint PCH only)
config INTEL_PMC_IPC
tristate "Intel PMC IPC Driver"
depends on ACPI && PCI
---help---
This driver provides support for PMC control on some Intel platforms.
The PMC is an ARC processor which defines IPC commands for communication
with other entities in the CPU.
config INTEL_PUNIT_IPC
tristate "Intel P-Unit IPC Driver"
---help---
@@ -1342,17 +1345,39 @@ config INTEL_PUNIT_IPC
which is used to bridge the communications between kernel and P-Unit.
config INTEL_SCU_IPC
bool "Intel SCU IPC Support"
depends on X86_INTEL_MID
default y
---help---
IPC is used to bridge the communications between kernel and SCU on
some embedded Intel x86 platforms. This is not needed for PC-type
machines.
bool
config INTEL_SCU
bool
select INTEL_SCU_IPC
config INTEL_SCU_PCI
bool "Intel SCU PCI driver"
depends on PCI
select INTEL_SCU
help
This driver is used to bridge the communications between kernel
and SCU on some embedded Intel x86 platforms. It also creates
devices that are connected to the SoC through the SCU.
Platforms supported:
Medfield
Clovertrail
Merrifield
Broxton
Apollo Lake
config INTEL_SCU_PLATFORM
tristate "Intel SCU platform driver"
depends on ACPI
select INTEL_SCU
help
This driver is used to bridge the communications between kernel
and SCU (sometimes called PMC as well). The driver currently
supports Intel Elkhart Lake and compatible platforms.
config INTEL_SCU_IPC_UTIL
tristate "Intel SCU IPC utility driver"
depends on INTEL_SCU_IPC
depends on INTEL_SCU
---help---
The IPC Util driver provides an interface with the SCU enabling
low level access for debug work and updating the firmware. Say
@@ -1360,7 +1385,9 @@ config INTEL_SCU_IPC_UTIL
config INTEL_TELEMETRY
tristate "Intel SoC Telemetry Driver"
depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_64
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

View File

@@ -11,6 +11,7 @@ obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o
# WMI drivers
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
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
@@ -138,9 +139,10 @@ obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.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_PMC_IPC) += intel_pmc_ipc.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_IPC_UTIL) += intel_scu_ipcutil.o
obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
intel_telemetry_pltdrv.o \

View File

@@ -827,7 +827,7 @@ MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnENBFT*:");
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTVR46*:");
MODULE_ALIAS("dmi:*:*Acer*:pnExtensa 5420*:");
MODULE_ALIAS("dmi:*:*Acer*:pnExtensa*5420*:");
module_init(acerhdf_init);
module_exit(acerhdf_exit);

View File

@@ -640,22 +640,15 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
static void asus_led_exit(struct asus_laptop *asus)
{
if (!IS_ERR_OR_NULL(asus->wled.led.dev))
led_classdev_unregister(&asus->wled.led);
if (!IS_ERR_OR_NULL(asus->bled.led.dev))
led_classdev_unregister(&asus->bled.led);
if (!IS_ERR_OR_NULL(asus->mled.led.dev))
led_classdev_unregister(&asus->mled.led);
if (!IS_ERR_OR_NULL(asus->tled.led.dev))
led_classdev_unregister(&asus->tled.led);
if (!IS_ERR_OR_NULL(asus->pled.led.dev))
led_classdev_unregister(&asus->pled.led);
if (!IS_ERR_OR_NULL(asus->rled.led.dev))
led_classdev_unregister(&asus->rled.led);
if (!IS_ERR_OR_NULL(asus->gled.led.dev))
led_classdev_unregister(&asus->gled.led);
if (!IS_ERR_OR_NULL(asus->kled.led.dev))
led_classdev_unregister(&asus->kled.led);
led_classdev_unregister(&asus->wled.led);
led_classdev_unregister(&asus->bled.led);
led_classdev_unregister(&asus->mled.led);
led_classdev_unregister(&asus->tled.led);
led_classdev_unregister(&asus->pled.led);
led_classdev_unregister(&asus->rled.led);
led_classdev_unregister(&asus->gled.led);
led_classdev_unregister(&asus->kled.led);
if (asus->led_workqueue) {
destroy_workqueue(asus->led_workqueue);
asus->led_workqueue = NULL;

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