mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
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:
22
Documentation/ABI/obsolete/sysfs-driver-intel_pmc_bxt
Normal file
22
Documentation/ABI/obsolete/sysfs-driver-intel_pmc_bxt
Normal 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.
|
||||
@@ -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
|
||||
36
MAINTAINERS
36
MAINTAINERS
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
91
arch/x86/include/asm/intel_scu_ipc_legacy.h
Normal file
91
arch/x86/include/asm/intel_scu_ipc_legacy.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
468
drivers/mfd/intel_pmc_bxt.c
Normal 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");
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user