Commit 67b8ed29 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull x86 platform driver updates from Andy Shevchenko:

 - New bootctl driver for Mellanox BlueField SoC.

 - New driver to support System76 laptops.

 - Temperature monitoring and fan control on Acer Aspire 7551 is now
   supported.

 - Previously the Huawei driver handled only hotkeys. After the
   conversion to WMI it has been expanded to support newer laptop
   models.

 - Big refactoring of intel-speed-select tools allows to use it on Intel
   CascadeLake-N systems.

 - Touchscreen support for ezpad 6 m4 and Schneider SCT101CTM tablets

 - Miscellaneous clean ups and fixes here and there.

* tag 'platform-drivers-x86-v5.5-1' of git://git.infradead.org/linux-platform-drivers-x86: (59 commits)
  platform/x86: hp-wmi: Fix ACPI errors caused by passing 0 as input size
  platform/x86: hp-wmi: Fix ACPI errors caused by too small buffer
  platform/x86: intel_pmc_core: Add Comet Lake (CML) platform support to intel_pmc_core driver
  platform/x86: intel_pmc_core: Fix the SoC naming inconsistency
  platform/mellanox: Fix Kconfig indentation
  tools/power/x86/intel-speed-select: Display TRL buckets for just base config level
  tools/power/x86/intel-speed-select: Ignore missing config level
  platform/x86: touchscreen_dmi: Add info for the ezpad 6 m4 tablet
  tools/power/x86/intel-speed-select: Increment version
  tools/power/x86/intel-speed-select: Use core count for base-freq mask
  tools/power/x86/intel-speed-select: Support platform with limited Intel(R) Speed Select
  tools/power/x86/intel-speed-select: Use Frequency weight for CLOS
  tools/power/x86/intel-speed-select: Make CLOS frequency in MHz
  tools/power/x86/intel-speed-select: Use mailbox for CLOS_PM_QOS_CONFIG
  tools/power/x86/intel-speed-select: Auto mode for CLX
  tools/power/x86/intel-speed-select: Correct CLX-N frequency units
  tools/power/x86/intel-speed-select: Change display of "avx" to "avx2"
  tools/power/x86/intel-speed-select: Extend command set for perf-profile
  Add touchscreen platform data for the Schneider SCT101CTM tablet
  platform/x86: intel_int0002_vgpio: Pass irqchip when adding gpiochip
  ...
parents d004701d f3e4f3fc
What: /sys/bus/platform/devices/MLNXBF04:00/driver/lifecycle_state
Date: Oct 2019
KernelVersion: 5.5
Contact: "Liming Sun <lsun@mellanox.com>"
Description:
The Life-cycle state of the SoC, which could be one of the
following values.
Production - Production state and can be updated to secure
GA Secured - Secure chip and not able to change state
GA Non-Secured - Non-Secure chip and not able to change state
RMA - Return Merchandise Authorization
What: /sys/bus/platform/devices/MLNXBF04:00/driver/post_reset_wdog
Date: Oct 2019
KernelVersion: 5.5
Contact: "Liming Sun <lsun@mellanox.com>"
Description:
The watchdog setting in seconds for the next booting. It's used
to reboot the chip and recover it to the old state if the new
boot partition fails.
What: /sys/bus/platform/devices/MLNXBF04:00/driver/reset_action
Date: Oct 2019
KernelVersion: 5.5
Contact: "Liming Sun <lsun@mellanox.com>"
Description:
The source of the boot stream for the next reset. It could be
one of the following values.
external - boot from external source (USB or PCIe)
emmc - boot from the onchip eMMC
emmc_legacy - boot from the onchip eMMC in legacy (slow) mode
What: /sys/bus/platform/devices/MLNXBF04:00/driver/second_reset_action
Date: Oct 2019
KernelVersion: 5.5
Contact: "Liming Sun <lsun@mellanox.com>"
Description:
Update the source of the boot stream after next reset. It could
be one of the following values and will be applied after next
reset.
external - boot from external source (USB or PCIe)
emmc - boot from the onchip eMMC
emmc_legacy - boot from the onchip eMMC in legacy (slow) mode
swap_emmc - swap the primary / secondary boot partition
none - cancel the action
What: /sys/bus/platform/devices/MLNXBF04:00/driver/secure_boot_fuse_state
Date: Oct 2019
KernelVersion: 5.5
Contact: "Liming Sun <lsun@mellanox.com>"
Description:
The state of eFuse versions with the following values.
InUse - burnt, valid and currently in use
Used - burnt and valid
Free - not burnt and free to use
Skipped - not burnt but not free (skipped)
Wasted - burnt and invalid
Invalid - not burnt but marked as valid (error state).
......@@ -295,7 +295,7 @@ S: Maintained
F: drivers/net/ethernet/alteon/acenic*
ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
M: Peter Feuerer <peter@piie.net>
M: Peter Kaestle <peter@piie.net>
L: platform-driver-x86@vger.kernel.org
W: http://piie.net/?section=acerhdf
S: Maintained
......@@ -10577,6 +10577,7 @@ M: Darren Hart <dvhart@infradead.org>
M: Vadim Pasternak <vadimp@mellanox.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
F: Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
F: drivers/platform/mellanox/
F: include/linux/platform_data/mlxreg.h
......@@ -15948,6 +15949,13 @@ F: drivers/hwtracing/stm/
F: include/linux/stm.h
F: include/uapi/linux/stm.h
SYSTEM76 ACPI DRIVER
M: Jeremy Soller <jeremy@system76.com>
M: System76 Product Development <productdev@system76.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/system76_acpi.c
SYSV FILESYSTEM
M: Christoph Hellwig <hch@infradead.org>
S: Maintained
......
......@@ -41,7 +41,19 @@ config MLXBF_TMFIFO
depends on VIRTIO_CONSOLE && VIRTIO_NET
help
Say y here to enable TmFifo support. The TmFifo driver provides
platform driver support for the TmFifo which supports console
and networking based on the virtio framework.
platform driver support for the TmFifo which supports console
and networking based on the virtio framework.
config MLXBF_BOOTCTL
tristate "Mellanox BlueField Firmware Boot Control driver"
depends on ARM64
depends on ACPI
help
The Mellanox BlueField firmware implements functionality to
request swapping the primary and alternate eMMC boot partition,
and to set up a watchdog that can undo that swap if the system
does not boot up correctly. This driver provides sysfs access
to the userspace tools, to be used in conjunction with the eMMC
device driver to do necessary initial swap of the boot partition.
endif # MELLANOX_PLATFORM
......@@ -3,6 +3,7 @@
# Makefile for linux/drivers/platform/mellanox
# Mellanox Platform-Specific Drivers
#
obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o
obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o
obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o
obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o
// SPDX-License-Identifier: GPL-2.0+
/*
* Mellanox boot control driver
*
* This driver provides a sysfs interface for systems management
* software to manage reset-time actions.
*
* Copyright (C) 2019 Mellanox Technologies
*/
#include <linux/acpi.h>
#include <linux/arm-smccc.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "mlxbf-bootctl.h"
#define MLXBF_BOOTCTL_SB_SECURE_MASK 0x03
#define MLXBF_BOOTCTL_SB_TEST_MASK 0x0c
#define MLXBF_SB_KEY_NUM 4
/* UUID used to probe ATF service. */
static const char *mlxbf_bootctl_svc_uuid_str =
"89c036b4-e7d7-11e6-8797-001aca00bfc4";
struct mlxbf_bootctl_name {
u32 value;
const char *name;
};
static struct mlxbf_bootctl_name boot_names[] = {
{ MLXBF_BOOTCTL_EXTERNAL, "external" },
{ MLXBF_BOOTCTL_EMMC, "emmc" },
{ MLNX_BOOTCTL_SWAP_EMMC, "swap_emmc" },
{ MLXBF_BOOTCTL_EMMC_LEGACY, "emmc_legacy" },
{ MLXBF_BOOTCTL_NONE, "none" },
};
static const char * const mlxbf_bootctl_lifecycle_states[] = {
[0] = "Production",
[1] = "GA Secured",
[2] = "GA Non-Secured",
[3] = "RMA",
};
/* ARM SMC call which is atomic and no need for lock. */
static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg)
{
struct arm_smccc_res res;
arm_smccc_smc(smc_op, smc_arg, 0, 0, 0, 0, 0, 0, &res);
return res.a0;
}
/* Return the action in integer or an error code. */
static int mlxbf_bootctl_reset_action_to_val(const char *action)
{
int i;
for (i = 0; i < ARRAY_SIZE(boot_names); i++)
if (sysfs_streq(boot_names[i].name, action))
return boot_names[i].value;
return -EINVAL;
}
/* Return the action in string. */
static const char *mlxbf_bootctl_action_to_string(int action)
{
int i;
for (i = 0; i < ARRAY_SIZE(boot_names); i++)
if (boot_names[i].value == action)
return boot_names[i].name;
return "invalid action";
}
static ssize_t post_reset_wdog_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_POST_RESET_WDOG, 0);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", ret);
}
static ssize_t post_reset_wdog_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long value;
int ret;
ret = kstrtoul(buf, 10, &value);
if (ret)
return ret;
ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_SET_POST_RESET_WDOG, value);
if (ret < 0)
return ret;
return count;
}
static ssize_t mlxbf_bootctl_show(int smc_op, char *buf)
{
int action;
action = mlxbf_bootctl_smc(smc_op, 0);
if (action < 0)
return action;
return sprintf(buf, "%s\n", mlxbf_bootctl_action_to_string(action));
}
static int mlxbf_bootctl_store(int smc_op, const char *buf, size_t count)
{
int ret, action;
action = mlxbf_bootctl_reset_action_to_val(buf);
if (action < 0)
return action;
ret = mlxbf_bootctl_smc(smc_op, action);
if (ret < 0)
return ret;
return count;
}
static ssize_t reset_action_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return mlxbf_bootctl_show(MLXBF_BOOTCTL_GET_RESET_ACTION, buf);
}
static ssize_t reset_action_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return mlxbf_bootctl_store(MLXBF_BOOTCTL_SET_RESET_ACTION, buf, count);
}
static ssize_t second_reset_action_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return mlxbf_bootctl_show(MLXBF_BOOTCTL_GET_SECOND_RESET_ACTION, buf);
}
static ssize_t second_reset_action_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
return mlxbf_bootctl_store(MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION, buf,
count);
}
static ssize_t lifecycle_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int lc_state;
lc_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE);
if (lc_state < 0)
return lc_state;
lc_state &=
MLXBF_BOOTCTL_SB_TEST_MASK | MLXBF_BOOTCTL_SB_SECURE_MASK;
/*
* If the test bits are set, we specify that the current state may be
* due to using the test bits.
*/
if (lc_state & MLXBF_BOOTCTL_SB_TEST_MASK) {
lc_state &= MLXBF_BOOTCTL_SB_SECURE_MASK;
return sprintf(buf, "%s(test)\n",
mlxbf_bootctl_lifecycle_states[lc_state]);
}
return sprintf(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]);
}
static ssize_t secure_boot_fuse_state_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int burnt, valid, key, key_state, buf_len = 0, upper_key_used = 0;
const char *status;
key_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS,
MLXBF_BOOTCTL_FUSE_STATUS_KEYS);
if (key_state < 0)
return key_state;
/*
* key_state contains the bits for 4 Key versions, loaded from eFuses
* after a hard reset. Lower 4 bits are a thermometer code indicating
* key programming has started for key n (0000 = none, 0001 = version 0,
* 0011 = version 1, 0111 = version 2, 1111 = version 3). Upper 4 bits
* are a thermometer code indicating key programming has completed for
* key n (same encodings as the start bits). This allows for detection
* of an interruption in the progamming process which has left the key
* partially programmed (and thus invalid). The process is to burn the
* eFuse for the new key start bit, burn the key eFuses, then burn the
* eFuse for the new key complete bit.
*
* For example 0000_0000: no key valid, 0001_0001: key version 0 valid,
* 0011_0011: key 1 version valid, 0011_0111: key version 2 started
* programming but did not complete, etc. The most recent key for which
* both start and complete bit is set is loaded. On soft reset, this
* register is not modified.
*/
for (key = MLXBF_SB_KEY_NUM - 1; key >= 0; key--) {
burnt = key_state & BIT(key);
valid = key_state & BIT(key + MLXBF_SB_KEY_NUM);
if (burnt && valid)
upper_key_used = 1;
if (upper_key_used) {
if (burnt)
status = valid ? "Used" : "Wasted";
else
status = valid ? "Invalid" : "Skipped";
} else {
if (burnt)
status = valid ? "InUse" : "Incomplete";
else
status = valid ? "Invalid" : "Free";
}
buf_len += sprintf(buf + buf_len, "%d:%s ", key, status);
}
buf_len += sprintf(buf + buf_len, "\n");
return buf_len;
}
static DEVICE_ATTR_RW(post_reset_wdog);
static DEVICE_ATTR_RW(reset_action);
static DEVICE_ATTR_RW(second_reset_action);
static DEVICE_ATTR_RO(lifecycle_state);
static DEVICE_ATTR_RO(secure_boot_fuse_state);
static struct attribute *mlxbf_bootctl_attrs[] = {
&dev_attr_post_reset_wdog.attr,
&dev_attr_reset_action.attr,
&dev_attr_second_reset_action.attr,
&dev_attr_lifecycle_state.attr,
&dev_attr_secure_boot_fuse_state.attr,
NULL
};
ATTRIBUTE_GROUPS(mlxbf_bootctl);
static const struct acpi_device_id mlxbf_bootctl_acpi_ids[] = {
{"MLNXBF04", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, mlxbf_bootctl_acpi_ids);
static bool mlxbf_bootctl_guid_match(const guid_t *guid,
const struct arm_smccc_res *res)
{
guid_t id = GUID_INIT(res->a0, res->a1, res->a1 >> 16,
res->a2, res->a2 >> 8, res->a2 >> 16,
res->a2 >> 24, res->a3, res->a3 >> 8,
res->a3 >> 16, res->a3 >> 24);
return guid_equal(guid, &id);
}
static int mlxbf_bootctl_probe(struct platform_device *pdev)
{
struct arm_smccc_res res = { 0 };
guid_t guid;
int ret;
/* Ensure we have the UUID we expect for this service. */
arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res);
guid_parse(mlxbf_bootctl_svc_uuid_str, &guid);
if (!mlxbf_bootctl_guid_match(&guid, &res))
return -ENODEV;
/*
* When watchdog is used, it sets boot mode to MLXBF_BOOTCTL_SWAP_EMMC
* in case of boot failures. However it doesn't clear the state if there
* is no failure. Restore the default boot mode here to avoid any
* unnecessary boot partition swapping.
*/
ret = mlxbf_bootctl_smc(MLXBF_BOOTCTL_SET_RESET_ACTION,
MLXBF_BOOTCTL_EMMC);
if (ret < 0)
dev_warn(&pdev->dev, "Unable to reset the EMMC boot mode\n");
return 0;
}
static struct platform_driver mlxbf_bootctl_driver = {
.probe = mlxbf_bootctl_probe,
.driver = {
.name = "mlxbf-bootctl",
.groups = mlxbf_bootctl_groups,
.acpi_match_table = mlxbf_bootctl_acpi_ids,
}
};
module_platform_driver(mlxbf_bootctl_driver);
MODULE_DESCRIPTION("Mellanox boot control driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Mellanox Technologies");
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019, Mellanox Technologies. All rights reserved.
*/
#ifndef __MLXBF_BOOTCTL_H__
#define __MLXBF_BOOTCTL_H__
/*
* Request that the on-chip watchdog be enabled, or disabled, after
* the next chip soft reset. This call does not affect the current
* status of the on-chip watchdog. If non-zero, the argument
* specifies the watchdog interval in seconds. If zero, the watchdog
* will not be enabled after the next soft reset. Non-zero errors are
* returned as documented below.
*/
#define MLXBF_BOOTCTL_SET_POST_RESET_WDOG 0x82000000
/*
* Query the status which has been requested for the on-chip watchdog
* after the next chip soft reset. Returns the interval as set by
* MLXBF_BOOTCTL_SET_POST_RESET_WDOG.
*/
#define MLXBF_BOOTCTL_GET_POST_RESET_WDOG 0x82000001
/*
* Request that a specific boot action be taken at the next soft
* reset. By default, the boot action is set by external chip pins,
* which are sampled on hard reset. Note that the boot action
* requested by this call will persist on subsequent resets unless
* this service, or the MLNX_SET_SECOND_RESET_ACTION service, is
* invoked. See below for the available MLNX_BOOT_xxx parameter
* values. Non-zero errors are returned as documented below.
*/
#define MLXBF_BOOTCTL_SET_RESET_ACTION 0x82000002
/*
* Return the specific boot action which will be taken at the next
* soft reset. Returns the reset action (see below for the parameter
* values for MLXBF_BOOTCTL_SET_RESET_ACTION).
*/
#define MLXBF_BOOTCTL_GET_RESET_ACTION 0x82000003
/*
* Request that a specific boot action be taken at the soft reset
* after the next soft reset. For a specified valid boot mode, the
* effect of this call is identical to that of invoking
* MLXBF_BOOTCTL_SET_RESET_ACTION after the next chip soft reset; in
* particular, after that reset, the action for the now next reset can
* be queried with MLXBF_BOOTCTL_GET_RESET_ACTION and modified with
* MLXBF_BOOTCTL_SET_RESET_ACTION. You may also specify the parameter as
* MLNX_BOOT_NONE, which is equivalent to specifying that no call to
* MLXBF_BOOTCTL_SET_RESET_ACTION be taken after the next chip soft reset.
* This call does not affect the action to be taken at the next soft
* reset. Non-zero errors are returned as documented below.
*/
#define MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION 0x82000004
/*
* Return the specific boot action which will be taken at the soft
* reset after the next soft reset; this will be one of the valid
* actions for MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION.
*/
#define MLXBF_BOOTCTL_GET_SECOND_RESET_ACTION 0x82000005
/*
* Return the fuse status of the current chip. The caller should specify
* with the second argument if the state of the lifecycle fuses or the
* version of secure boot fuse keys left should be returned.
*/
#define MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS 0x82000006
/* Reset eMMC by programming the RST_N register. */
#define MLXBF_BOOTCTL_SET_EMMC_RST_N 0x82000007
#define MLXBF_BOOTCTL_GET_DIMM_INFO 0x82000008
/* SMC function IDs for SiP Service queries */
#define MLXBF_BOOTCTL_SIP_SVC_CALL_COUNT 0x8200ff00
#define MLXBF_BOOTCTL_SIP_SVC_UID 0x8200ff01
#define MLXBF_BOOTCTL_SIP_SVC_VERSION 0x8200ff03
/* ARM Standard Service Calls version numbers */
#define MLXBF_BOOTCTL_SVC_VERSION_MAJOR 0x0
#define MLXBF_BOOTCTL_SVC_VERSION_MINOR 0x2
/* Number of svc calls defined. */
#define MLXBF_BOOTCTL_NUM_SVC_CALLS 12
/* Valid reset actions for MLXBF_BOOTCTL_SET_RESET_ACTION. */
#define MLXBF_BOOTCTL_EXTERNAL 0 /* Not boot from eMMC */
#define MLXBF_BOOTCTL_EMMC 1 /* From primary eMMC boot partition */
#define MLNX_BOOTCTL_SWAP_EMMC 2 /* Swap eMMC boot partitions and reboot */
#define MLXBF_BOOTCTL_EMMC_LEGACY 3 /* From primary eMMC in legacy mode */
/* Valid arguments for requesting the fuse status. */
#define MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE 0 /* Return lifecycle status. */
#define MLXBF_BOOTCTL_FUSE_STATUS_KEYS 1 /* Return secure boot key status */
/* Additional value to disable the MLXBF_BOOTCTL_SET_SECOND_RESET_ACTION. */
#define MLXBF_BOOTCTL_NONE 0x7fffffff /* Don't change next boot action */
#endif /* __MLXBF_BOOTCTL_H__ */
......@@ -94,7 +94,6 @@ config ASUS_LAPTOP
depends on RFKILL || RFKILL = n
depends on ACPI_VIDEO || ACPI_VIDEO = n
select INPUT_SPARSEKMAP
select INPUT_POLLDEV
---help---
This is a driver for Asus laptops, Lenovo SL and the Pegatron
Lucid tablet. It may also support some MEDION, JVC or VICTOR
......@@ -623,7 +622,6 @@ config THINKPAD_ACPI_HOTKEY_POLL
config SENSORS_HDAPS
tristate "Thinkpad Hard Drive Active Protection System (hdaps)"
depends on INPUT
select INPUT_POLLDEV
help
This driver provides support for the IBM Hard Drive Active Protection
System (hdaps), which provides an accelerometer and other misc. data.
......@@ -806,7 +804,6 @@ config PEAQ_WMI
tristate "PEAQ 2-in-1 WMI hotkey driver"
depends on ACPI_WMI
depends on INPUT
select INPUT_POLLDEV
help
Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s.
......@@ -834,7 +831,6 @@ config ACPI_TOSHIBA
depends on ACPI_VIDEO || ACPI_VIDEO = n
depends on RFKILL || RFKILL = n
depends on IIO
select INPUT_POLLDEV
select INPUT_SPARSEKMAP
---help---
This driver adds support for access to certain system settings
......@@ -931,14 +927,20 @@ config INTEL_CHT_INT33FE
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 3 devices: Maxim MAX17047 Fuel Gauge Controller,
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_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m.
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.
config INTEL_INT0002_VGPIO
tristate "Intel ACPI INT0002 Virtual GPIO driver"
......@@ -1305,7 +1307,8 @@ config INTEL_ATOMISP2_PM
will be called intel_atomisp2_pm.
config HUAWEI_WMI
tristate "Huawei WMI hotkeys driver"
tristate "Huawei WMI laptop extras driver"
depends on ACPI_BATTERY
depends on ACPI_WMI
depends on INPUT
select INPUT_SPARSEKMAP
......@@ -1314,9 +1317,8 @@ config HUAWEI_WMI
select LEDS_TRIGGER_AUDIO
select NEW_LEDS
help
This driver provides support for Huawei WMI hotkeys.
It enables the missing keys and adds support to the micmute
LED found on some of these laptops.
This driver provides support for Huawei WMI hotkeys, battery charge
control, fn-lock, mic-mute LED, and other extra features.
To compile this driver as a module, choose M here: the module
will be called huawei-wmi.
......@@ -1337,6 +1339,19 @@ config PCENGINES_APU2
source "drivers/platform/x86/intel_speed_select_if/Kconfig"
config SYSTEM76_ACPI
tristate "System76 ACPI Driver"
depends on ACPI
select NEW_LEDS
select LEDS_CLASS
select LEDS_TRIGGERS
help
This is a driver for System76 laptops running open firmware. It adds
support for Fn-Fx key combinations, keyboard backlight, and airplane mode
LEDs.
If you have a System76 laptop running open firmware, say Y or M here.
endif # X86_PLATFORM_DEVICES
config PMC_ATOM
......
......@@ -61,6 +61,10 @@ obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o
obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
intel_cht_int33fe-objs := intel_cht_int33fe_common.o \
intel_cht_int33fe_typec.o \
intel_cht_int33fe_microb.o
obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
......@@ -100,3 +104,4 @@ obj-$(CONFIG_I2C_MULTI_INSTANTIATE) += i2c-multi-instantiate.o
obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/
obj-$(CONFIG_SYSTEM76_ACPI) += system76_acpi.o
......@@ -4,7 +4,7 @@
* of the aspire one netbook, turns on/off the fan
* as soon as the upper/lower threshold is reached.
*
* (C) 2009 - Peter Feuerer peter (a) piie.net
* (C) 2009 - Peter Kaestle peter (a) piie.net
* http://piie.net
* 2009 Borislav Petkov bp (a) alien8.de
*
......@@ -224,6 +224,8 @@ static const struct bios_settings bios_tbl[] __initconst = {
{"Acer", "Aspire 5739G", "V1.3311", 0x55, 0x58, {0x20, 0x00}, 0},
/* Acer TravelMate 7730 */
{"Acer", "TravelMate 7730G", "v0.3509", 0x55, 0x58, {0xaf, 0x00}, 0},
/* Acer Aspire 7551 */
{"Acer", "Aspire 7551", "V1.18", 0x93, 0xa8, {0x14, 0x04}, 1},
/* Acer TravelMate TM8573T */
{"Acer", "TM8573T", "V1.13", 0x93, 0xa8, {0x14, 0x04}, 1},
/* Gateway */
......@@ -801,7 +803,7 @@ static void __exit acerhdf_exit(void)
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Feuerer");
MODULE_AUTHOR("Peter Kaestle");
MODULE_DESCRIPTION("Aspire One temperature and fan driver");
MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
MODULE_ALIAS("dmi:*:*Acer*:pnAO751h*:");
......@@ -815,6 +817,7 @@ MODULE_ALIAS("dmi:*:*Acer*:pnAspire*5739G:");
MODULE_ALIAS("dmi:*:*Acer*:pnAspire*One*753:");
MODULE_ALIAS("dmi:*:*Acer*:pnAspire*5315:");
MODULE_ALIAS("dmi:*:*Acer*:TravelMate*7730G:");
MODULE_ALIAS("dmi:*:*Acer*:pnAspire*7551:");
MODULE_ALIAS("dmi:*:*Acer*:TM8573T:");
MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
......
......@@ -34,7 +34,6 @@
#include <linux/uaccess.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/input-polldev.h>
#include <linux/rfkill.h>
#include <linux/slab.h>
#include <linux/dmi.h>
......@@ -244,7 +243,7 @@ struct asus_laptop {
struct input_dev *inputdev;
struct key_entry *keymap;
struct input_polled_dev *pega_accel_poll;
struct input_dev *pega_accel_poll;
struct asus_led wled;
struct asus_led bled;
......@@ -446,9 +445,9 @@ static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method)
return clamp_val((short)val, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP);
}
static void pega_accel_poll(struct input_polled_dev *ipd)
static void pega_accel_poll(struct input_dev *input)
{
struct device *parent = ipd->input->dev.parent;
struct device *parent = input->dev.parent;
struct asus_laptop *asus = dev_get_drvdata(parent);
/* In some cases, the very first call to poll causes a
......@@ -457,10 +456,10 @@ static void pega_accel_poll(struct input_polled_dev *ipd)
* device, and perhaps a firmware bug. Fake the first report. */
if (!asus->pega_acc_live) {
asus->pega_acc_live = true;
input_report_abs(ipd->input, ABS_X, 0);
input_report_abs(ipd->input, ABS_Y, 0);
input_report_abs(ipd->input, ABS_Z, 0);
input_sync(ipd->input);
input_report_abs(input, ABS_X, 0);
input_report_abs(input, ABS_Y, 0);
input_report_abs(input, ABS_Z, 0);
input_sync(input);
return;
}
......@@ -471,25 +470,24 @@ static void pega_accel_poll(struct input_polled_dev *ipd)
/* Note transform, convert to "right/up/out" in the native
* landscape orientation (i.e. the vector is the direction of
* "real up" in the device's cartiesian coordinates). */
input_report_abs(ipd->input, ABS_X, -asus->pega_acc_x);
input_report_abs(ipd->input, ABS_Y, -asus->pega_acc_y);
input_report_abs(ipd->input, ABS_Z, asus->pega_acc_z);
input_sync(ipd->input);
input_report_abs(input, ABS_X, -asus->pega_acc_x);
input_report_abs(input, ABS_Y, -asus->pega_acc_y);
input_report_abs(input, ABS_Z, asus->pega_acc_z);
input_sync(input);
}
static void pega_accel_exit(struct asus_laptop *asus)
{
if (asus->pega_accel_poll) {
input_unregister_polled_device(asus->pega_accel_poll);
input_free_polled_device(asus->pega_accel_poll);
input_unregister_device(asus->pega_accel_poll);
asus->pega_accel_poll = NULL;
}
asus->pega_accel_poll = NULL;
}
static int pega_accel_init(struct asus_laptop *asus)
{
int err;
struct input_polled_dev *ipd;
struct input_dev *input;
if (!asus->is_pega_lucid)
return -ENODEV;
......@@ -499,37 +497,39 @@ static int pega_accel_init(struct asus_laptop *asus)
acpi_check_handle(asus->handle, METHOD_XLRZ, NULL))
return -ENODEV;
ipd = input_allocate_polled_device();
if (!ipd)
input = input_allocate_device();
if (!input)
return -ENOMEM;
ipd->poll = pega_accel_poll;
ipd->poll_interval = 125;
ipd->poll_interval_min = 50;
ipd->poll_interval_max = 2000;
ipd->input->name = PEGA_ACCEL_DESC;
ipd->input->phys = PEGA_ACCEL_NAME "/input0";
ipd->input->dev.parent = &asus->platform_device->dev;
ipd->input->id.bustype = BUS_HOST;
input->name = PEGA_ACCEL_DESC;
input->phys = PEGA_ACCEL_NAME "/input0";
input->dev.parent = &asus->platform_device->dev;
input->id.bustype = BUS_HOST;
set_bit(EV_ABS, ipd->input->evbit);
input_set_abs_params(ipd->input, ABS_X,
input_set_abs_params(input, ABS_X,
-PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
input_set_abs_params(ipd->input, ABS_Y,
input_set_abs_params(input, ABS_Y,
-PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
input_set_abs_params(ipd->input, ABS_Z,
input_set_abs_params(input, ABS_Z,
-PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0);
err = input_register_polled_device(ipd);
err = input_setup_polling(input, pega_accel_poll);
if (err)
goto exit;
asus->pega_accel_poll = ipd;
input_set_poll_interval(input, 125);
input_set_min_poll_interval(input, 50);
input_set_max_poll_interval(input, 2000);
err = input_register_device(input);
if (err)
goto exit;
asus->pega_accel_poll = input;
return 0;
exit:
input_free_polled_device(ipd);
input_free_device(input);
return err;
}
......@@ -1550,8 +1550,7 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
/* Accelerometer "coarse orientation change" event */
if (asus->pega_accel_poll && event == 0xEA) {
kobject_uevent(&asus->pega_accel_poll->input->dev.kobj,
KOBJ_CHANGE);
kobject_uevent(&asus->pega_accel_poll->dev.kobj, KOBJ_CHANGE);
return ;
}
......
......@@ -33,6 +33,7 @@
struct quirk_entry {
bool touchpad_led;
bool kbd_led_not_present;
bool kbd_led_levels_off_1;
bool kbd_missing_ac_tag;
......@@ -73,6 +74,10 @@ static struct quirk_entry quirk_dell_latitude_e6410 = {
.kbd_led_levels_off_1 = true,
};
static struct quirk_entry quirk_dell_inspiron_1012 = {
.kbd_led_not_present = true,
};
static struct platform_driver platform_driver = {
.driver = {
.name = "dell-laptop",
......@@ -310,6 +315,24 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
},
.driver_data = &quirk_dell_latitude_e6410,
},
{
.callback = dmi_matched,
.ident = "Dell Inspiron 1012",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
},
.driver_data = &quirk_dell_inspiron_1012,
},
{
.callback = dmi_matched,
.ident = "Dell Inspiron 1018",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1018"),
},
.driver_data = &quirk_dell_inspiron_1012,
},
{ }
};
......@@ -1493,6 +1516,9 @@ static void kbd_init(void)
{
int ret;
if (quirks && quirks->kbd_led_not_present)
return;
ret = kbd_init_info();
kbd_init_tokens();
......
......@@ -18,7 +18,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/module.h>
......@@ -59,7 +59,7 @@
#define HDAPS_BOTH_AXES (HDAPS_X_AXIS | HDAPS_Y_AXIS)
static struct platform_device *pdev;
static struct input_polled_dev *hdaps_idev;
static struct input_dev *hdaps_idev;
static unsigned int hdaps_invert;
static u8 km_activity;
static int rest_x;
......@@ -318,9 +318,8 @@ static void hdaps_calibrate(void)
__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
}
static void hdaps_mousedev_poll(struct input_polled_dev *dev)
static void hdaps_mousedev_poll(struct input_dev *input_dev)
{
struct input_dev *input_dev = dev->input;
int x, y;
mutex_lock(&hdaps_mtx);
......@@ -531,7 +530,6 @@ static const struct dmi_system_id hdaps_whitelist[] __initconst = {
static int __init hdaps_init(void)
{
struct input_dev *idev;
int ret;
if (!dmi_check_system(hdaps_whitelist)) {
......@@ -559,31 +557,32 @@ static int __init hdaps_init(void)
if (ret)
goto out_device;
hdaps_idev = input_allocate_polled_device();
hdaps_idev = input_allocate_device();
if (!hdaps_idev) {
ret = -ENOMEM;
goto out_group;
}
hdaps_idev->poll = hdaps_mousedev_poll;
hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL;
/* initial calibrate for the input device */
hdaps_calibrate();
/* initialize the input class */
idev = hdaps_idev->input;
idev->name = "hdaps";
idev->phys = "isa1600/input0";
idev->id.bustype = BUS_ISA;
idev->dev.parent = &pdev->dev;
idev->evbit[0] = BIT_MASK(EV_ABS);
input_set_abs_params(idev, ABS_X,
hdaps_idev->name = "hdaps";
hdaps_idev->phys = "isa1600/input0";
hdaps_idev->id.bustype = BUS_ISA;
hdaps_idev->dev.parent = &pdev->dev;
input_set_abs_params(hdaps_idev, ABS_X,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
input_set_abs_params(idev, ABS_Y,
input_set_abs_params(hdaps_idev, ABS_Y,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
ret = input_register_polled_device(hdaps_idev);
ret = input_setup_polling(hdaps_idev, hdaps_mousedev_poll);
if (ret)
goto out_idev;
input_set_poll_interval(hdaps_idev, HDAPS_POLL_INTERVAL);
ret = input_register_device(hdaps_idev);
if (ret)
goto out_idev;
......@@ -591,7 +590,7 @@ static int __init hdaps_init(void)
return 0;
out_idev:
input_free_polled_device(hdaps_idev);
input_free_device(hdaps_idev);
out_group:
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
out_device:
......@@ -607,8 +606,7 @@ static int __init hdaps_init(void)
static void __exit hdaps_exit(void)
{
input_unregister_polled_device(hdaps_idev);
input_free_polled_device(hdaps_idev);
input_unregister_device(hdaps_idev);
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
platform_device_unregister(pdev);
platform_driver_unregister(&hdaps_driver);
......
......@@ -65,7 +65,7 @@ struct bios_args {
u32 command;
u32 commandtype;
u32 datasize;
u32 data;
u8 data[128];
};
enum hp_wmi_commandtype {
......@@ -216,7 +216,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
.command = command,
.commandtype = query,
.datasize = insize,
.data = 0,
.data = { 0 },
};
struct acpi_buffer input = { sizeof(struct bios_args), &args };
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
......@@ -228,7 +228,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
if (WARN_ON(insize > sizeof(args.data)))
return -EINVAL;
memcpy(&args.data, buffer, insize);
memcpy(&args.data[0], buffer, insize);
wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
......@@ -380,7 +380,7 @@ static int hp_wmi_rfkill2_refresh(void)
int err, i;
err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
0, sizeof(state));
sizeof(state), sizeof(state));
if (err)
return err;
......@@ -778,7 +778,7 @@ static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
int err, i;
err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
0, sizeof(state));
sizeof(state), sizeof(state));
if (err)
return err < 0 ? err : -EINVAL;
......
This diff is collapsed.
// 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_i2c_res_filter(struct acpi_resource *ares, void *data)
{
struct acpi_resource_i2c_serialbus *sb;
int *count = data;
if (i2c_acpi_get_i2c_resource(ares, &sb))
(*count)++;
return 1;
}
static int cht_int33fe_count_i2c_clients(struct device *dev)
{
struct acpi_device *adev;
LIST_HEAD(resource_list);
int count = 0;
adev = ACPI_COMPANION(dev);
if (!adev)
return -EINVAL;
acpi_dev_get_resources(adev, &resource_list,
cht_int33fe_i2c_res_filter, &count);
acpi_dev_free_resource_list(&resource_list);
return count;
}
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 = cht_int33fe_count_i2c_clients(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),
{ }
};
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.properties = bq27xxx_props;
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;
}
......@@ -17,17 +17,15 @@
* for these chips can bind to the them.
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/interrupt.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>
#define EXPECTED_PTYPE 4
#include "intel_cht_int33fe_common.h"
enum {
INT33FE_NODE_FUSB302,
......@@ -38,14 +36,6 @@ enum {
INT33FE_NODE_MAX,
};
struct cht_int33fe_data {
struct i2c_client *max17047;
struct i2c_client *fusb302;
struct i2c_client *pi3usb30532;
struct fwnode_handle *dp;
};
static const struct software_node nodes[];
static const struct software_node_ref_args pi3usb30532_ref = {
......@@ -251,43 +241,20 @@ cht_int33fe_register_max17047(struct device *dev, struct cht_int33fe_data *data)
strlcpy(board_info.type, "max17047", I2C_NAME_SIZE);
board_info.dev_name = "max17047";
board_info.fwnode = fwnode;
data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info);
return PTR_ERR_OR_ZERO(data->max17047);
return PTR_ERR_OR_ZERO(data->battery_fg);
}
static int cht_int33fe_probe(struct platform_device *pdev)
int cht_int33fe_typec_probe(struct cht_int33fe_data *data)
{
struct device *dev = &pdev->dev;
struct device *dev = data->dev;
struct i2c_board_info board_info;
struct cht_int33fe_data *data;
struct fwnode_handle *fwnode;
struct regulator *regulator;
unsigned long long ptyp;
acpi_status status;
int fusb302_irq;
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;
}
/*
* 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:
......@@ -317,10 +284,6 @@ static int cht_int33fe_probe(struct platform_device *pdev)
return fusb302_irq;
}
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
ret = cht_int33fe_add_nodes(data);
if (ret)
return ret;
......@@ -365,15 +328,13 @@ static int cht_int33fe_probe(struct platform_device *pdev)
goto out_unregister_fusb302;
}
platform_set_drvdata(pdev, data);
return 0;
out_unregister_fusb302:
i2c_unregister_device(data->fusb302);
out_unregister_max17047:
i2c_unregister_device(data->max17047);
i2c_unregister_device(data->battery_fg);
out_remove_nodes:
cht_int33fe_remove_nodes(data);
......@@ -381,36 +342,13 @@ static int cht_int33fe_probe(struct platform_device *pdev)
return ret;
}
static int cht_int33fe_remove(struct platform_device *pdev)
int cht_int33fe_typec_remove(struct cht_int33fe_data *data)
{
struct cht_int33fe_data *data = platform_get_drvdata(pdev);
i2c_unregister_device(data->pi3usb30532);
i2c_unregister_device(data->fusb302);
i2c_unregister_device(data->max17047);
i2c_unregister_device(data->battery_fg);
cht_int33fe_remove_nodes(data);
return 0;
}
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("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL v2");
......@@ -164,8 +164,8 @@ static int int0002_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct x86_cpu_id *cpu_id;
struct irq_chip *irq_chip;
struct gpio_chip *chip;
struct gpio_irq_chip *girq;
int irq, ret;
/* Menlow has a different INT0002 device? <sigh> */
......@@ -192,15 +192,11 @@ static int int0002_probe(struct platform_device *pdev)
chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1;
chip->irq.init_valid_mask = int0002_init_irq_valid_mask;
ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL);
if (ret) {
dev_err(dev, "Error adding gpio chip: %d\n", ret);
return ret;
}
/*
* We manually request the irq here instead of passing a flow-handler
* We directly request the irq here instead of passing a flow-handler
* to gpiochip_set_chained_irqchip, because the irq is shared.
* FIXME: augment this if we managed to pull handling of shared
* IRQs into gpiolib.
*/
ret = devm_request_irq(dev, irq, int0002_irq,
IRQF_SHARED, "INT0002", chip);
......@@ -209,17 +205,21 @@ static int int0002_probe(struct platform_device *pdev)
return ret;
}
irq_chip = (struct irq_chip *)cpu_id->driver_data;
girq = &chip->irq;
girq->chip = (struct irq_chip *)cpu_id->driver_data;
/* This let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
ret = gpiochip_irqchip_add(chip, irq_chip, 0, handle_edge_irq,
IRQ_TYPE_NONE);
ret = devm_gpiochip_add_data(dev, chip, NULL);
if (ret) {
dev_err(dev, "Error adding irqchip: %d\n", ret);
dev_err(dev, "Error adding gpio chip: %d\n", ret);
return ret;
}
gpiochip_set_chained_irqchip(chip, irq_chip, irq, NULL);
device_init_wakeup(dev, true);
return 0;
}
......
......@@ -158,8 +158,9 @@ static const struct pmc_reg_map spt_reg_map = {
.pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,
};
/* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */
/* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */
static const struct pmc_bit_map cnp_pfear_map[] = {
/* Reserved for Cannon Lake but valid for Comet Lake */
{"PMC", BIT(0)},
{"OPI-DMI", BIT(1)},
{"SPI/eSPI", BIT(2)},
......@@ -185,7 +186,7 @@ static const struct pmc_bit_map cnp_pfear_map[] = {
{"SDX", BIT(4)},
{"SPE", BIT(5)},
{"Fuse", BIT(6)},
/* Reserved for Cannonlake but valid for Icelake */
/* Reserved for Cannon Lake but valid for Ice Lake and Comet Lake */
{"SBR8", BIT(7)},
{"CSME_FSC", BIT(0)},
......@@ -229,12 +230,12 @@ static const struct pmc_bit_map cnp_pfear_map[] = {
{"HDA_PGD4", BIT(2)},
{"HDA_PGD5", BIT(3)},
{"HDA_PGD6", BIT(4)},
/* Reserved for Cannonlake but valid for Icelake */
/* Reserved for Cannon Lake but valid for Ice Lake and Comet Lake */
{"PSF6", BIT(5)},
{"PSF7", BIT(6)},
{"PSF8", BIT(7)},
/* Icelake generation onwards only */
/* Ice Lake generation onwards only */
{"RES_65", BIT(0)},
{"RES_66", BIT(1)},
{"RES_67", BIT(2)},
......@@ -324,7 +325,7 @@ static const struct pmc_bit_map cnp_ltr_show_map[] = {
{"ISH", CNP_PMC_LTR_ISH},
{"UFSX2", CNP_PMC_LTR_UFSX2},
{"EMMC", CNP_PMC_LTR_EMMC},
/* Reserved for Cannonlake but valid for Icelake */
/* Reserved for Cannon Lake but valid for Ice Lake */
{"WIGIG", ICL_PMC_LTR_WIGIG},
/* Below two cannot be used for LTR_IGNORE */
{"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT},
......@@ -813,6 +814,8 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
INTEL_CPU_FAM6(CANNONLAKE_L, cnp_reg_map),
INTEL_CPU_FAM6(ICELAKE_L, icl_reg_map),
INTEL_CPU_FAM6(ICELAKE_NNPI, icl_reg_map),
INTEL_CPU_FAM6(COMETLAKE, cnp_reg_map),
INTEL_CPU_FAM6(COMETLAKE_L, cnp_reg_map),
{}
};
......@@ -871,8 +874,8 @@ static int pmc_core_probe(struct platform_device *pdev)
pmcdev->map = (struct pmc_reg_map *)cpu_id->driver_data;
/*
* Coffeelake has CPU ID of Kabylake and Cannonlake PCH. So here
* Sunrisepoint PCH regmap can't be used. Use Cannonlake PCH regmap
* Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here
* Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap
* in this case.
*/
if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids))
......
......@@ -224,7 +224,6 @@ static irqreturn_t intel_punit_ioc(int irq, void *dev_id)
static int intel_punit_get_bars(struct platform_device *pdev)
{
struct resource *res;
void __iomem *addr;
/*
......@@ -232,14 +231,12 @@ static int intel_punit_get_bars(struct platform_device *pdev)
* - BIOS_IPC BASE_DATA
* - BIOS_IPC BASE_IFACE
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = devm_ioremap_resource(&pdev->dev, res);
addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(addr))
return PTR_ERR(addr);
punit_ipcdev->base[BIOS_IPC][BASE_DATA] = addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
addr = devm_ioremap_resource(&pdev->dev, res);
addr = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(addr))
return PTR_ERR(addr);
punit_ipcdev->base[BIOS_IPC][BASE_IFACE] = addr;
......@@ -251,33 +248,21 @@ static int intel_punit_get_bars(struct platform_device *pdev)
* - GTDRIVER_IPC BASE_DATA
* - GTDRIVER_IPC BASE_IFACE
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
if (res) {
addr = devm_ioremap_resource(&pdev->dev, res);
if (!IS_ERR(addr))
punit_ipcdev->base[ISPDRIVER_IPC][BASE_DATA] = addr;
}
addr = devm_platform_ioremap_resource(pdev, 2);
if (!IS_ERR(addr))
punit_ipcdev->base[ISPDRIVER_IPC][BASE_DATA] = addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
if (res) {
addr = devm_ioremap_resource(&pdev->dev, res);
if (!IS_ERR(addr))
punit_ipcdev->base[ISPDRIVER_IPC][BASE_IFACE] = addr;
}
addr = devm_platform_ioremap_resource(pdev, 3);
if (!IS_ERR(addr))
punit_ipcdev->base[ISPDRIVER_IPC][BASE_IFACE] = addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
if (res) {
addr = devm_ioremap_resource(&pdev->dev, res);
if (!IS_ERR(addr))
punit_ipcdev->base[GTDRIVER_IPC][BASE_DATA] = addr;
}
addr = devm_platform_ioremap_resource(pdev, 4);
if (!IS_ERR(addr))
punit_ipcdev->base[GTDRIVER_IPC][BASE_DATA] = addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 5);
if (res) {
addr = devm_ioremap_resource(&pdev->dev, res);
if (!IS_ERR(addr))
punit_ipcdev->base[GTDRIVER_IPC][BASE_IFACE] = addr;
}
addr = devm_platform_ioremap_resource(pdev, 5);
if (!IS_ERR(addr))
punit_ipcdev->base[GTDRIVER_IPC][BASE_IFACE] = addr;
return 0;
}
......@@ -309,14 +294,13 @@ static int intel_punit_ipc_probe(struct platform_device *pdev)
ret = intel_punit_get_bars(pdev);
if (ret)
goto out;
return ret;
punit_ipcdev->dev = &pdev->dev;
mutex_init(&punit_ipcdev->lock);
init_completion(&punit_ipcdev->cmd_complete);
out:
return ret;
return 0;
}
static int intel_punit_ipc_remove(struct platform_device *pdev)
......
......@@ -6,7 +6,7 @@
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/input-polldev.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
......@@ -18,8 +18,7 @@
MODULE_ALIAS("wmi:"PEAQ_DOLBY_BUTTON_GUID);
static unsigned int peaq_ignore_events_counter;
static struct input_polled_dev *peaq_poll_dev;
static struct input_dev *peaq_poll_dev;
/*
* The Dolby button (yes really a Dolby button) causes an ACPI variable to get
......@@ -28,8 +27,10 @@ static struct input_polled_dev *peaq_poll_dev;
* (if polling after the release) or twice (polling between press and release).
* We ignore events for 0.5s after the first event to avoid reporting 2 presses.
*/
static void peaq_wmi_poll(struct input_polled_dev *dev)
static void peaq_wmi_poll(struct input_dev *input_dev)
{
static unsigned long last_event_time;
static bool had_events;
union acpi_object obj;
acpi_status status;
u32 dummy = 0;
......@@ -44,22 +45,25 @@ static void peaq_wmi_poll(struct input_polled_dev *dev)
return;
if (obj.type != ACPI_TYPE_INTEGER) {
dev_err(&peaq_poll_dev->input->dev,
dev_err(&input_dev->dev,
"Error WMBC did not return an integer\n");
return;
}
if (peaq_ignore_events_counter && peaq_ignore_events_counter--)
if (!obj.integer.value)
return;
if (obj.integer.value) {
input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 1);
input_sync(peaq_poll_dev->input);
input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 0);
input_sync(peaq_poll_dev->input);
peaq_ignore_events_counter = max(1u,
PEAQ_POLL_IGNORE_MS / peaq_poll_dev->poll_interval);
}
if (had_events && time_before(jiffies, last_event_time +
msecs_to_jiffies(PEAQ_POLL_IGNORE_MS)))
return;
input_event(input_dev, EV_KEY, KEY_SOUND, 1);
input_sync(input_dev);
input_event(input_dev, EV_KEY, KEY_SOUND, 0);
input_sync(input_dev);
last_event_time = jiffies;
had_events = true;
}
/* Some other devices (Shuttle XS35) use the same WMI GUID for other purposes */
......@@ -75,6 +79,8 @@ static const struct dmi_system_id peaq_dmi_table[] __initconst = {
static int __init peaq_wmi_init(void)
{
int err;
/* WMI GUID is not unique, also check for a DMI match */
if (!dmi_check_system(peaq_dmi_table))
return -ENODEV;
......@@ -82,24 +88,36 @@ static int __init peaq_wmi_init(void)
if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
return -ENODEV;
peaq_poll_dev = input_allocate_polled_device();
peaq_poll_dev = input_allocate_device();
if (!peaq_poll_dev)
return -ENOMEM;
peaq_poll_dev->poll = peaq_wmi_poll;
peaq_poll_dev->poll_interval = PEAQ_POLL_INTERVAL_MS;
peaq_poll_dev->poll_interval_max = PEAQ_POLL_MAX_MS;
peaq_poll_dev->input->name = "PEAQ WMI hotkeys";
peaq_poll_dev->input->phys = "wmi/input0";
peaq_poll_dev->input->id.bustype = BUS_HOST;
input_set_capability(peaq_poll_dev->input, EV_KEY, KEY_SOUND);
peaq_poll_dev->name = "PEAQ WMI hotkeys";
peaq_poll_dev->phys = "wmi/input0";
peaq_poll_dev->id.bustype = BUS_HOST;
input_set_capability(peaq_poll_dev, EV_KEY, KEY_SOUND);
err = input_setup_polling(peaq_poll_dev, peaq_wmi_poll);
if (err)
goto err_out;
input_set_poll_interval(peaq_poll_dev, PEAQ_POLL_INTERVAL_MS);
input_set_max_poll_interval(peaq_poll_dev, PEAQ_POLL_MAX_MS);
err = input_register_device(peaq_poll_dev);
if (err)
goto err_out;
return 0;
return input_register_polled_device(peaq_poll_dev);
err_out:
input_free_device(peaq_poll_dev);
return err;
}
static void __exit peaq_wmi_exit(void)
{
input_unregister_polled_device(peaq_poll_dev);
input_unregister_device(peaq_poll_dev);
}
module_init(peaq_wmi_init);
......
// SPDX-License-Identifier: GPL-2.0+
/*
* System76 ACPI Driver
*
* Copyright (C) 2019 System76
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/pci_ids.h>
#include <linux/types.h>
struct system76_data {
struct acpi_device *acpi_dev;
struct led_classdev ap_led;
struct led_classdev kb_led;
enum led_brightness kb_brightness;
enum led_brightness kb_toggle_brightness;
int kb_color;
};
static const struct acpi_device_id device_ids[] = {
{"17761776", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, device_ids);
// Array of keyboard LED brightness levels
static const enum led_brightness kb_levels[] = {
48,
72,
96,
144,
192,
255
};
// Array of keyboard LED colors in 24-bit RGB format
static const int kb_colors[] = {
0xFFFFFF,
0x0000FF,
0xFF0000,
0xFF00FF,
0x00FF00,
0x00FFFF,
0xFFFF00
};
// Get a System76 ACPI device value by name
static int system76_get(struct system76_data *data, char *method)
{
acpi_handle handle;
acpi_status status;
unsigned long long ret = 0;
handle = acpi_device_handle(data->acpi_dev);
status = acpi_evaluate_integer(handle, method, NULL, &ret);
if (ACPI_SUCCESS(status))
return (int)ret;
else
return -1;
}
// Set a System76 ACPI device value by name
static int system76_set(struct system76_data *data, char *method, int value)
{
union acpi_object obj;
struct acpi_object_list obj_list;
acpi_handle handle;
acpi_status status;
obj.type = ACPI_TYPE_INTEGER;
obj.integer.value = value;
obj_list.count = 1;
obj_list.pointer = &obj;
handle = acpi_device_handle(data->acpi_dev);
status = acpi_evaluate_object(handle, method, &obj_list, NULL);
if (ACPI_SUCCESS(status))
return 0;
else
return -1;
}
// Get the airplane mode LED brightness
static enum led_brightness ap_led_get(struct led_classdev *led)
{
struct system76_data *data;
int value;
data = container_of(led, struct system76_data, ap_led);
value = system76_get(data, "GAPL");
if (value > 0)
return (enum led_brightness)value;
else
return LED_OFF;
}
// Set the airplane mode LED brightness
static void ap_led_set(struct led_classdev *led, enum led_brightness value)
{
struct system76_data *data;
data = container_of(led, struct system76_data, ap_led);
system76_set(data, "SAPL", value == LED_OFF ? 0 : 1);
}
// Get the last set keyboard LED brightness
static enum led_brightness kb_led_get(struct led_classdev *led)
{
struct system76_data *data;
data = container_of(led, struct system76_data, kb_led);
return data->kb_brightness;
}
// Set the keyboard LED brightness
static void kb_led_set(struct led_classdev *led, enum led_brightness value)
{
struct system76_data *data;
data = container_of(led, struct system76_data, kb_led);
data->kb_brightness = value;
system76_set(data, "SKBL", (int)data->kb_brightness);
}
// Get the last set keyboard LED color
static ssize_t kb_led_color_show(
struct device *dev,
struct device_attribute *dev_attr,
char *buf)
{
struct led_classdev *led;
struct system76_data *data;
led = (struct led_classdev *)dev->driver_data;
data = container_of(led, struct system76_data, kb_led);
return sprintf(buf, "%06X\n", data->kb_color);
}
// Set the keyboard LED color
static ssize_t kb_led_color_store(
struct device *dev,
struct device_attribute *dev_attr,
const char *buf,
size_t size)
{
struct led_classdev *led;
struct system76_data *data;
unsigned int val;
int ret;
led = (struct led_classdev *)dev->driver_data;
data = container_of(led, struct system76_data, kb_led);
ret = kstrtouint(buf, 16, &val);
if (ret)
return ret;
if (val > 0xFFFFFF)
return -EINVAL;
data->kb_color = (int)val;
system76_set(data, "SKBC", data->kb_color);
return size;
}
static const struct device_attribute kb_led_color_dev_attr = {
.attr = {
.name = "color",
.mode = 0644,
},
.show = kb_led_color_show,
.store = kb_led_color_store,
};
// Notify that the keyboard LED was changed by hardware
static void kb_led_notify(struct system76_data *data)
{
led_classdev_notify_brightness_hw_changed(
&data->kb_led,
data->kb_brightness
);
}
// Read keyboard LED brightness as set by hardware
static void kb_led_hotkey_hardware(struct system76_data *data)
{
int value;
value = system76_get(data, "GKBL");
if (value < 0)
return;
data->kb_brightness = value;
kb_led_notify(data);
}
// Toggle the keyboard LED
static void kb_led_hotkey_toggle(struct system76_data *data)
{
if (data->kb_brightness > 0) {
data->kb_toggle_brightness = data->kb_brightness;
kb_led_set(&data->kb_led, 0);
} else {
kb_led_set(&data->kb_led, data->kb_toggle_brightness);
}
kb_led_notify(data);
}
// Decrease the keyboard LED brightness
static void kb_led_hotkey_down(struct system76_data *data)
{
int i;
if (data->kb_brightness > 0) {
for (i = ARRAY_SIZE(kb_levels); i > 0; i--) {
if (kb_levels[i - 1] < data->kb_brightness) {
kb_led_set(&data->kb_led, kb_levels[i - 1]);
break;
}
}
} else {
kb_led_set(&data->kb_led, data->kb_toggle_brightness);
}
kb_led_notify(data);
}
// Increase the keyboard LED brightness
static void kb_led_hotkey_up(struct system76_data *data)
{
int i;
if (data->kb_brightness > 0) {
for (i = 0; i < ARRAY_SIZE(kb_levels); i++) {
if (kb_levels[i] > data->kb_brightness) {
kb_led_set(&data->kb_led, kb_levels[i]);
break;
}
}
} else {
kb_led_set(&data->kb_led, data->kb_toggle_brightness);
}
kb_led_notify(data);
}
// Cycle the keyboard LED color
static void kb_led_hotkey_color(struct system76_data *data)
{
int i;
if (data->kb_color < 0)
return;
if (data->kb_brightness > 0) {
for (i = 0; i < ARRAY_SIZE(kb_colors); i++) {
if (kb_colors[i] == data->kb_color)
break;
}
i += 1;
if (i >= ARRAY_SIZE(kb_colors))
i = 0;
data->kb_color = kb_colors[i];
system76_set(data, "SKBC", data->kb_color);
} else {
kb_led_set(&data->kb_led, data->kb_toggle_brightness);
}
kb_led_notify(data);
}
// Handle ACPI notification
static void system76_notify(struct acpi_device *acpi_dev, u32 event)
{
struct system76_data *data;
data = acpi_driver_data(acpi_dev);
switch (event) {
case 0x80:
kb_led_hotkey_hardware(data);
break;
case 0x81:
kb_led_hotkey_toggle(data);
break;
case 0x82:
kb_led_hotkey_down(data);
break;
case 0x83:
kb_led_hotkey_up(data);
break;
case 0x84:
kb_led_hotkey_color(data);
break;
}
}
// Add a System76 ACPI device
static int system76_add(struct acpi_device *acpi_dev)
{
struct system76_data *data;
int err;
data = devm_kzalloc(&acpi_dev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
acpi_dev->driver_data = data;
data->acpi_dev = acpi_dev;
err = system76_get(data, "INIT");
if (err)
return err;
data->ap_led.name = "system76_acpi::airplane";
data->ap_led.flags = LED_CORE_SUSPENDRESUME;
data->ap_led.brightness_get = ap_led_get;
data->ap_led.brightness_set = ap_led_set;
data->ap_led.max_brightness = 1;
data->ap_led.default_trigger = "rfkill-none";
err = devm_led_classdev_register(&acpi_dev->dev, &data->ap_led);
if (err)
return err;
data->kb_led.name = "system76_acpi::kbd_backlight";
data->kb_led.flags = LED_BRIGHT_HW_CHANGED | LED_CORE_SUSPENDRESUME;
data->kb_led.brightness_get = kb_led_get;
data->kb_led.brightness_set = kb_led_set;
if (acpi_has_method(acpi_device_handle(data->acpi_dev), "SKBC")) {
data->kb_led.max_brightness = 255;
data->kb_toggle_brightness = 72;
data->kb_color = 0xffffff;
system76_set(data, "SKBC", data->kb_color);
} else {
data->kb_led.max_brightness = 5;
data->kb_color = -1;
}
err = devm_led_classdev_register(&acpi_dev->dev, &data->kb_led);
if (err)
return err;
if (data->kb_color >= 0) {
err = device_create_file(
data->kb_led.dev,
&kb_led_color_dev_attr
);
if (err)
return err;
}
return 0;
}
// Remove a System76 ACPI device
static int system76_remove(struct acpi_device *acpi_dev)
{
struct system76_data *data;
data = acpi_driver_data(acpi_dev);
if (data->kb_color >= 0)
device_remove_file(data->kb_led.dev, &kb_led_color_dev_attr);
devm_led_classdev_unregister(&acpi_dev->dev, &data->ap_led);
devm_led_classdev_unregister(&acpi_dev->dev, &data->kb_led);
system76_get(data, "FINI");
return 0;
}
static struct acpi_driver system76_driver = {
.name = "System76 ACPI Driver",
.class = "hotkey",
.ids = device_ids,
.ops = {
.add = system76_add,
.remove = system76_remove,
.notify = system76_notify,
},
};
module_acpi_driver(system76_driver);
MODULE_DESCRIPTION("System76 ACPI Driver");
MODULE_AUTHOR("Jeremy Soller <jeremy@system76.com>");
MODULE_LICENSE("GPL");
......@@ -310,6 +310,22 @@ static const struct ts_dmi_data jumper_ezpad_6_pro_b_data = {
.properties = jumper_ezpad_6_pro_b_props,
};
static const struct property_entry jumper_ezpad_6_m4_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 35),
PROPERTY_ENTRY_U32("touchscreen-min-y", 15),
PROPERTY_ENTRY_U32("touchscreen-size-x", 1950),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1525),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-m4.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
static const struct ts_dmi_data jumper_ezpad_6_m4_data = {
.acpi_name = "MSSL1680:00",
.properties = jumper_ezpad_6_m4_props,
};
static const struct property_entry jumper_ezpad_mini3_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 23),
PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
......@@ -498,6 +514,24 @@ static const struct ts_dmi_data pov_mobii_wintab_p1006w_v10_data = {
.properties = pov_mobii_wintab_p1006w_v10_props,
};
static const struct property_entry schneider_sct101ctm_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1715),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
"gsl1680-schneider-sct101ctm.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
static const struct ts_dmi_data schneider_sct101ctm_data = {
.acpi_name = "MSSL1680:00",
.properties = schneider_sct101ctm_props,
};
static const struct property_entry teclast_x3_plus_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
......@@ -788,6 +822,16 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_BIOS_DATE, "04/24/2018"),
},
},
{
/* Jumper EZpad 6 m4 */
.driver_data = (void *)&jumper_ezpad_6_m4_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "jumper"),
DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
/* Jumper8.S106x.A00C.1066 with the version dropped */
DMI_MATCH(DMI_BIOS_VERSION, "Jumper8.S106x"),
},
},
{
/* Jumper EZpad mini3 */
.driver_data = (void *)&jumper_ezpad_mini3_data,
......@@ -908,6 +952,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"),
},
},
{
/* Schneider SCT101CTM */
.driver_data = (void *)&schneider_sct101ctm_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Default string"),
DMI_MATCH(DMI_PRODUCT_NAME, "SCT101CTM"),
},
},
{
/* Teclast X3 Plus */
.driver_data = (void *)&teclast_x3_plus_data,
......
......@@ -2,7 +2,7 @@
/*
* gov_bang_bang.c - A simple thermal throttling governor using hysteresis
*
* Copyright (C) 2014 Peter Feuerer <peter@piie.net>
* Copyright (C) 2014 Peter Kaestle <peter@piie.net>
*
* Based on step_wise.c with following Copyrights:
* Copyright (C) 2012 Intel Corp
......
......@@ -13,8 +13,14 @@ int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
ret = isst_send_mbox_command(cpu, CONFIG_TDP,
CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
if (ret)
return ret;
if (ret) {
pkg_dev->levels = 0;
pkg_dev->locked = 1;
pkg_dev->current_level = 0;
pkg_dev->version = 0;
pkg_dev->enabled = 0;
return 0;
}
debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
......@@ -95,6 +101,69 @@ int isst_get_pwr_info(int cpu, int config_index,
return 0;
}
void isst_get_uncore_p0_p1_info(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
unsigned int resp;
int ret;
ret = isst_send_mbox_command(cpu, CONFIG_TDP,
CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
config_index, &resp);
if (ret) {
ctdp_level->uncore_p0 = 0;
ctdp_level->uncore_p1 = 0;
return;
}
ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
debug_printf(
"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
cpu, config_index, resp, ctdp_level->uncore_p0,
ctdp_level->uncore_p1);
}
void isst_get_p1_info(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
unsigned int resp;
int ret;
ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
config_index, &resp);
if (ret) {
ctdp_level->sse_p1 = 0;
ctdp_level->avx2_p1 = 0;
ctdp_level->avx512_p1 = 0;
return;
}
ctdp_level->sse_p1 = resp & GENMASK(7, 0);
ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
debug_printf(
"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
cpu, config_index, resp, ctdp_level->sse_p1,
ctdp_level->avx2_p1, ctdp_level->avx512_p1);
}
void isst_get_uncore_mem_freq(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
unsigned int resp;
int ret;
ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
0, config_index, &resp);
if (ret) {
ctdp_level->mem_freq = 0;
return;
}
ctdp_level->mem_freq = resp & GENMASK(7, 0);
debug_printf(
"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
cpu, config_index, resp, ctdp_level->mem_freq);
}
int isst_get_tjmax_info(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
......@@ -149,6 +218,27 @@ int isst_get_coremask_info(int cpu, int config_index,
return 0;
}
int isst_get_get_trl_from_msr(int cpu, int *trl)
{
unsigned long long msr_trl;
int ret;
ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
if (ret)
return ret;
trl[0] = msr_trl & GENMASK(7, 0);
trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
return 0;
}
int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
{
unsigned int req, resp;
......@@ -245,12 +335,15 @@ int isst_set_tdp_level(int cpu, int tdp_level)
int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
{
int i, ret, core_cnt, max;
unsigned int req, resp;
int i, ret;
pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
for (i = 0; i < 2; ++i) {
core_cnt = get_core_count(get_physical_package_id(cpu), get_physical_die_id(cpu));
max = core_cnt > 32 ? 2 : 1;
for (i = 0; i < max; ++i) {
unsigned long long mask;
int count;
......@@ -258,7 +351,7 @@ int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
0, (i << 8) | level, &resp);
if (ret)
return ret;
break;
debug_printf(
"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
......@@ -323,7 +416,7 @@ int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
ret = isst_get_ctdp_levels(cpu, &pkg_dev);
if (ret)
return ret;
debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
current_level = pkg_dev.current_level;
......@@ -553,7 +646,6 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
i);
ctdp_level = &pkg_dev->ctdp_level[i];
ctdp_level->processed = 1;
ctdp_level->level = i;
ctdp_level->control_cpu = cpu;
ctdp_level->pkg_id = get_physical_package_id(cpu);
......@@ -561,7 +653,37 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
ret = isst_get_ctdp_control(cpu, i, ctdp_level);
if (ret)
return ret;
continue;
pkg_dev->processed = 1;
ctdp_level->processed = 1;
if (ctdp_level->pbf_support) {
ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
if (!ret)
ctdp_level->pbf_found = 1;
}
if (ctdp_level->fact_support) {
ret = isst_get_fact_info(cpu, i,
&ctdp_level->fact_info);
if (ret)
return ret;
}
if (!pkg_dev->enabled) {
int freq;
freq = get_cpufreq_base_freq(cpu);
if (freq > 0) {
ctdp_level->sse_p1 = freq / 100000;
ctdp_level->tdp_ratio = ctdp_level->sse_p1;
}
isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores);
isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
continue;
}
ret = isst_get_tdp_info(cpu, i, ctdp_level);
if (ret)
......@@ -600,22 +722,11 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
if (ret)
return ret;
if (ctdp_level->pbf_support) {
ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
if (!ret)
ctdp_level->pbf_found = 1;
}
if (ctdp_level->fact_support) {
ret = isst_get_fact_info(cpu, i,
&ctdp_level->fact_info);
if (ret)
return ret;
}
isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
isst_get_p1_info(cpu, i, ctdp_level);
isst_get_uncore_mem_freq(cpu, i, ctdp_level);
}
pkg_dev->processed = 1;
return 0;
}
......@@ -649,6 +760,27 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
unsigned int req, resp;
int ret;
if (!enable_clos) {
struct isst_pkg_ctdp pkg_dev;
struct isst_pkg_ctdp_level_info ctdp_level;
ret = isst_get_ctdp_levels(cpu, &pkg_dev);
if (ret) {
debug_printf("isst_get_ctdp_levels\n");
return ret;
}
ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
&ctdp_level);
if (ret)
return ret;
if (ctdp_level.fact_enabled) {
debug_printf("Turbo-freq feature must be disabled first\n");
return -EINVAL;
}
}
ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
&resp);
if (ret)
......
......@@ -6,8 +6,6 @@
#include "isst.h"
#define DISP_FREQ_MULTIPLIER 100
static void printcpulist(int str_len, char *str, int mask_size,
cpu_set_t *cpu_mask)
{
......@@ -204,6 +202,9 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
format_and_print(outf, disp_level + 1, header, value);
if (is_clx_n_platform())
return;
snprintf(header, sizeof(header), "tjunction-temperature(C)");
snprintf(value, sizeof(value), "%d", pbf_info->t_prochot);
format_and_print(outf, disp_level + 1, header, value);
......@@ -314,7 +315,8 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
char value[256];
int i, base_level = 1;
print_package_info(cpu, outf);
if (pkg_dev->processed)
print_package_info(cpu, outf);
for (i = 0; i <= pkg_dev->levels; ++i) {
struct isst_pkg_ctdp_level_info *ctdp_level;
......@@ -334,27 +336,66 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
snprintf(value, sizeof(value), "%d", j);
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header), "enable-cpu-mask");
printcpumask(sizeof(value), value,
ctdp_level->core_cpumask_size,
ctdp_level->core_cpumask);
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header), "enable-cpu-list");
printcpulist(sizeof(value), value,
ctdp_level->core_cpumask_size,
ctdp_level->core_cpumask);
format_and_print(outf, base_level + 4, header, value);
if (ctdp_level->core_cpumask_size) {
snprintf(header, sizeof(header), "enable-cpu-mask");
printcpumask(sizeof(value), value,
ctdp_level->core_cpumask_size,
ctdp_level->core_cpumask);
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header), "enable-cpu-list");
printcpulist(sizeof(value), value,
ctdp_level->core_cpumask_size,
ctdp_level->core_cpumask);
format_and_print(outf, base_level + 4, header, value);
}
snprintf(header, sizeof(header), "thermal-design-power-ratio");
snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header), "base-frequency(MHz)");
if (!ctdp_level->sse_p1)
ctdp_level->sse_p1 = ctdp_level->tdp_ratio;
snprintf(value, sizeof(value), "%d",
ctdp_level->tdp_ratio * DISP_FREQ_MULTIPLIER);
ctdp_level->sse_p1 * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 4, header, value);
if (ctdp_level->avx2_p1) {
snprintf(header, sizeof(header), "base-frequency-avx2(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->avx2_p1 * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 4, header, value);
}
if (ctdp_level->avx512_p1) {
snprintf(header, sizeof(header), "base-frequency-avx512(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->avx512_p1 * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 4, header, value);
}
if (ctdp_level->uncore_p1) {
snprintf(header, sizeof(header), "uncore-frequency-min(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->uncore_p1 * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 4, header, value);
}
if (ctdp_level->uncore_p0) {
snprintf(header, sizeof(header), "uncore-frequency-max(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->uncore_p0 * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 4, header, value);
}
if (ctdp_level->mem_freq) {
snprintf(header, sizeof(header), "mem-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->mem_freq * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 4, header, value);
}
snprintf(header, sizeof(header),
"speed-select-turbo-freq");
if (ctdp_level->fact_support) {
......@@ -377,13 +418,26 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
snprintf(value, sizeof(value), "unsupported");
format_and_print(outf, base_level + 4, header, value);
snprintf(header, sizeof(header), "thermal-design-power(W)");
snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
format_and_print(outf, base_level + 4, header, value);
if (is_clx_n_platform()) {
if (ctdp_level->pbf_support)
_isst_pbf_display_information(cpu, outf,
tdp_level,
&ctdp_level->pbf_info,
base_level + 4);
continue;
}
snprintf(header, sizeof(header), "tjunction-max(C)");
snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
format_and_print(outf, base_level + 4, header, value);
if (ctdp_level->pkg_tdp) {
snprintf(header, sizeof(header), "thermal-design-power(W)");
snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
format_and_print(outf, base_level + 4, header, value);
}
if (ctdp_level->t_proc_hot) {
snprintf(header, sizeof(header), "tjunction-max(C)");
snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
format_and_print(outf, base_level + 4, header, value);
}
snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
format_and_print(outf, base_level + 4, header, NULL);
......@@ -402,41 +456,41 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 6, header, value);
}
snprintf(header, sizeof(header), "turbo-ratio-limits-avx");
format_and_print(outf, base_level + 4, header, NULL);
for (j = 0; j < 8; ++j) {
snprintf(header, sizeof(header), "bucket-%d", j);
format_and_print(outf, base_level + 5, header, NULL);
snprintf(header, sizeof(header), "core-count");
snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
format_and_print(outf, base_level + 6, header, value);
if (ctdp_level->trl_avx_active_cores[0]) {
snprintf(header, sizeof(header), "turbo-ratio-limits-avx2");
format_and_print(outf, base_level + 4, header, NULL);
for (j = 0; j < 8; ++j) {
snprintf(header, sizeof(header), "bucket-%d", j);
format_and_print(outf, base_level + 5, header, NULL);
snprintf(header, sizeof(header),
"max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->trl_avx_active_cores[j] *
DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 6, header, value);
snprintf(header, sizeof(header), "core-count");
snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
format_and_print(outf, base_level + 6, header, value);
snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_active_cores[j] * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 6, header, value);
}
}
snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
format_and_print(outf, base_level + 4, header, NULL);
for (j = 0; j < 8; ++j) {
snprintf(header, sizeof(header), "bucket-%d", j);
format_and_print(outf, base_level + 5, header, NULL);
if (ctdp_level->trl_avx_512_active_cores[0]) {
snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
format_and_print(outf, base_level + 4, header, NULL);
for (j = 0; j < 8; ++j) {
snprintf(header, sizeof(header), "bucket-%d", j);
format_and_print(outf, base_level + 5, header, NULL);
snprintf(header, sizeof(header), "core-count");
snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
format_and_print(outf, base_level + 6, header, value);
snprintf(header, sizeof(header), "core-count");
snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
format_and_print(outf, base_level + 6, header, value);
snprintf(header, sizeof(header),
"max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->trl_avx_512_active_cores[j] *
DISP_FREQ_MULTIPLIER);
snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_512_active_cores[j] * DISP_FREQ_MULTIPLIER);
format_and_print(outf, base_level + 6, header, value);
}
}
if (ctdp_level->pbf_support)
_isst_pbf_display_information(cpu, outf, i,
&ctdp_level->pbf_info,
......@@ -509,15 +563,15 @@ void isst_clos_display_information(int cpu, FILE *outf, int clos,
format_and_print(outf, 5, header, value);
snprintf(header, sizeof(header), "clos-min");
snprintf(value, sizeof(value), "%d", clos_config->clos_min);
snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * DISP_FREQ_MULTIPLIER);
format_and_print(outf, 5, header, value);
snprintf(header, sizeof(header), "clos-max");
snprintf(value, sizeof(value), "%d", clos_config->clos_max);
snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER);
format_and_print(outf, 5, header, value);
snprintf(header, sizeof(header), "clos-desired");
snprintf(value, sizeof(value), "%d", clos_config->clos_desired);
snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * DISP_FREQ_MULTIPLIER);
format_and_print(outf, 5, header, value);
format_and_print(outf, 1, NULL, NULL);
......
......@@ -69,6 +69,8 @@
#define PM_CLOS_OFFSET 0x08
#define PQR_ASSOC_OFFSET 0x20
#define DISP_FREQ_MULTIPLIER 100
struct isst_clos_config {
int pkg_id;
int die_id;
......@@ -161,6 +163,7 @@ struct isst_pkg_ctdp {
extern int get_topo_max_cpus(void);
extern int get_cpu_count(int pkg_id, int die_id);
extern int get_core_count(int pkg_id, int die_id);
/* Common interfaces */
extern void debug_printf(const char *format, ...);
......@@ -237,4 +240,6 @@ extern void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
extern int isst_clos_get_clos_information(int cpu, int *enable, int *type);
extern void isst_clos_display_clos_information(int cpu, FILE *outf,
int clos_enable, int type);
extern int is_clx_n_platform(void);
extern int get_cpufreq_base_freq(int cpu);
#endif
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