mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 03:40:52 +07:00
platform-drivers-x86 for v5.9-1
* ASUS WMI driver honors BAT1 name of the battery (quite a few new laptops are using it) * Dell WMI driver supports new key codes and backlight events * ThinkPad ACPI driver now may use standard charge threshold interface, it also has been updated to provide Laptop or Desktop mode to the user * Intel Speed Select Technology gained support on Sapphire Rapids platform * Regular update of Speed Select Technology tools * Mellanox has been updated to support complex attributes * PMC core driver has been fixed to show correct names for LPM0 register * HTTP links were replaced by HTTPS ones where it applies * Miscellaneous fixes and cleanups here and there The following is an automated git shortlog grouped by driver: acerhdf: - Replace HTTP links with HTTPS ones Add new intel_atomisp2_led driver: - Add new intel_atomisp2_led driver apple-gmux: - Replace HTTP links with HTTPS ones asus-nb-wmi: - Drop duplicate DMI quirk structures - add support for ASUS ROG Zephyrus G14 and G15 asus-wmi: - allow BAT1 battery name dell-wmi: - add new dmi mapping for keycode 0xffff - add new keymap type 0x0012 - add new backlight events intel_cht_int33fe: - Drop double check for ACPI companion device intel-hid: - Fix return value check in check_acpi_dev() intel_pmc_core: - fix bound check in pmc_core_mphy_pg_show() - update TGL's LPM0 reg bit map name intel-vbtn: - Fix return value check in check_acpi_dev() ISST: - drop a duplicated word in isst_if.h - Add new PCI device ids pcengines-apuv2: - revert wiring up simswitch GPIO as LED platform/mellanox: - Introduce string_upper() and string_lower() helpers - Add string_upper() and string_lower() tests - Extend FAN platform data description - Add more definitions for system attributes - Add new attribute for mlxreg-io sysfs interfaces - Add presence register field for FAN devices - Add support for complex attributes - mlxreg-io: Add support for complex attributes - mlxreg-hotplug: Add environmental data to uevent - mlxreg-hotplug: Use capability register for attribute creation - mlxreg-hotplug: Modify module license system76-acpi: - Fix brightness_set schedule while atomic thinkpad_acpi: - Make some symbols static - add documentation for battery charge control - use standard charge control attribute names - remove unused defines - Replace HTTP links with HTTPS ones - not loading brightness_init when _BCL invalid - lap or desk mode interface - Revert "Use strndup_user() in dispatch_proc_write()" tools/power/x86/intel-speed-select: - Update version for v5.9 - Add retries for mail box commands - Add option to delay mbox commands - Ignore -o option processing on error - Change path for caching topology info -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEqaflIX74DDDzMJJtb7wzTHR8rCgFAl8n9UIACgkQb7wzTHR8 rCg0cRAAnHC699qMns53T+jSMAc9kY5vrwbf2Bacwjp5vYS7uw3S12kLNgQh6JWM B8imS1RAMlHfCvGT9vUs+mbpemCfYpFZ0HQ4z+VMzziKayJu8pCD9O2XDS9lRUHj uKqA19FX6lXfJnrhRoi3vM0JC35FXZQZkueLyJ728t1xqcDkNS2/O/by3c76XnK1 r81jl9m+qMJwB5zt+6qeSWjZAgFCTDvOHA/gZTEKF1VBOcafN1RHWTLH49JtpBH7 +pPoy9mw3zfDJReqKxFhaXgDlueBlRwTBG5kEQk9aIxgA9T8q2jqEyAw5XtAKOWp RCebgCpC5NHXyz/2CVzaJWYikS/Iuvr4ynx6F2nKXVClGMtF7Obb2/3rvSCOTMri ge1bJ2NomUL9F5Cd/iR/F4/jNtxk9LSuzW+otA+/m+g8UkK574cefQQmBdrhrfDU GqK6C1kB7OQW2v3tPKVsWvduXQTaaCVzINEkdUxK50PXZayY7+w0djM+QFR/sadw 2/okr1zuNjFnEt7HtZRP5bzEm1ofXVo5JIaCnpwgsz6dCQH4NiuVxsc/GyanRpBJ AadUAYcD+PRRnOybsfhx5MlUt/JIr6cV0OvT8LlWPINJjTpWPlqMeBYdDUOLCndX 3LXmoZ0k8IQ2LLmONc5UBX1+iayCO+PkHcBDoJdNuWT1eoO06M8= =yvnW -----END PGP SIGNATURE----- Merge tag 'platform-drivers-x86-v5.9-1' of git://git.infradead.org/linux-platform-drivers-x86 Pull x86 platform driver updates from Andy Shevchenko: - ASUS WMI driver honors BAT1 name of the battery (quite a few new laptops are using it) - Dell WMI driver supports new key codes and backlight events - ThinkPad ACPI driver now may use standard charge threshold interface, it also has been updated to provide Laptop or Desktop mode to the user - Intel Speed Select Technology gained support on Sapphire Rapids platform - Regular update of Speed Select Technology tools - Mellanox has been updated to support complex attributes - PMC core driver has been fixed to show correct names for LPM0 register - HTTP links were replaced by HTTPS ones where it applies - Miscellaneous fixes and cleanups here and there * tag 'platform-drivers-x86-v5.9-1' of git://git.infradead.org/linux-platform-drivers-x86: (42 commits) platform/x86: asus-nb-wmi: Drop duplicate DMI quirk structures platform/x86: thinkpad_acpi: Make some symbols static platform/x86: thinkpad_acpi: add documentation for battery charge control platform/x86: thinkpad_acpi: use standard charge control attribute names platform/x86: thinkpad_acpi: remove unused defines platform/x86: ISST: drop a duplicated word in isst_if.h tools/power/x86/intel-speed-select: Update version for v5.9 tools/power/x86/intel-speed-select: Add retries for mail box commands tools/power/x86/intel-speed-select: Add option to delay mbox commands tools/power/x86/intel-speed-select: Ignore -o option processing on error tools/power/x86/intel-speed-select: Change path for caching topology info platform/x86: acerhdf: Replace HTTP links with HTTPS ones platform/x86: apple-gmux: Replace HTTP links with HTTPS ones platform/x86: pcengines-apuv2: revert wiring up simswitch GPIO as LED platform/x86: mlx-platform: Extend FAN platform data description platform_data/mlxreg: Add presence register field for FAN devices Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces platform/mellanox: mlxreg-io: Add support for complex attributes platform/x86: mlx-platform: Add more definitions for system attributes platform_data/mlxreg: Add support for complex attributes ...
This commit is contained in:
commit
09a0bd0776
@ -206,3 +206,20 @@ Description: This file exposes the firmware version of burnable voltage
|
||||
regulator devices.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_pn
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_pn
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_pn
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_pn
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld1_version_min
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld2_version_min
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_version_min
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_version_min
|
||||
Date: July 2020
|
||||
KernelVersion: 5.9
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
Description: These files show with which CPLD part numbers and minor
|
||||
versions have been burned CPLD devices equipped on a
|
||||
system.
|
||||
|
||||
The files are read only.
|
||||
|
@ -50,6 +50,7 @@ detailed description):
|
||||
- WAN enable and disable
|
||||
- UWB enable and disable
|
||||
- LCD Shadow (PrivacyGuard) enable and disable
|
||||
- Lap mode sensor
|
||||
|
||||
A compatibility table by model and feature is maintained on the web
|
||||
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
|
||||
@ -1432,6 +1433,20 @@ The first command ensures the best viewing angle and the latter one turns
|
||||
on the feature, restricting the viewing angles.
|
||||
|
||||
|
||||
DYTC Lapmode sensor
|
||||
------------------
|
||||
|
||||
sysfs: dytc_lapmode
|
||||
|
||||
Newer thinkpads and mobile workstations have the ability to determine if
|
||||
the device is in deskmode or lapmode. This feature is used by user space
|
||||
to decide if WWAN transmission can be increased to maximum power and is
|
||||
also useful for understanding the different thermal modes available as
|
||||
they differ between desk and lap mode.
|
||||
|
||||
The property is read-only. If the platform doesn't have support the sysfs
|
||||
class is not created.
|
||||
|
||||
EXPERIMENTAL: UWB
|
||||
-----------------
|
||||
|
||||
@ -1470,6 +1485,23 @@ For more details about which buttons will appear depending on the mode, please
|
||||
review the laptop's user guide:
|
||||
http://www.lenovo.com/shop/americas/content/user_guides/x1carbon_2_ug_en.pdf
|
||||
|
||||
Battery charge control
|
||||
----------------------
|
||||
|
||||
sysfs attributes:
|
||||
/sys/class/power_supply/BAT*/charge_control_{start,end}_threshold
|
||||
|
||||
These two attributes are created for those batteries that are supported by the
|
||||
driver. They enable the user to control the battery charge thresholds of the
|
||||
given battery. Both values may be read and set. `charge_control_start_threshold`
|
||||
accepts an integer between 0 and 99 (inclusive); this value represents a battery
|
||||
percentage level, below which charging will begin. `charge_control_end_threshold`
|
||||
accepts an integer between 1 and 100 (inclusive); this value represents a battery
|
||||
percentage level, above which charging will stop.
|
||||
|
||||
The exact semantics of the attributes may be found in
|
||||
Documentation/ABI/testing/sysfs-class-power.
|
||||
|
||||
Multiple Commands, Module Parameters
|
||||
------------------------------------
|
||||
|
||||
|
@ -8610,6 +8610,12 @@ L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/platform/x86/intel_atomisp2_pm.c
|
||||
|
||||
INTEL ATOMISP2 LED DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/platform/x86/intel_atomisp2_led.c
|
||||
|
||||
INTEL BROXTON PMC DRIVER
|
||||
M: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
M: Zha Qipeng <qipeng.zha@intel.com>
|
||||
|
@ -1,34 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2016-2018 Vadim Pasternak <vadimp@mellanox.com>
|
||||
* Mellanox hotplug driver
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* Copyright (C) 2016-2020 Mellanox Technologies
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
@ -42,6 +16,7 @@
|
||||
#include <linux/platform_data/mlxreg.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
@ -97,6 +72,23 @@ struct mlxreg_hotplug_priv_data {
|
||||
u8 not_asserted;
|
||||
};
|
||||
|
||||
/* Environment variables array for udev. */
|
||||
static char *mlxreg_hotplug_udev_envp[] = { NULL, NULL };
|
||||
|
||||
static int
|
||||
mlxreg_hotplug_udev_event_send(struct kobject *kobj,
|
||||
struct mlxreg_core_data *data, bool action)
|
||||
{
|
||||
char event_str[MLXREG_CORE_LABEL_MAX_SIZE + 2];
|
||||
char label[MLXREG_CORE_LABEL_MAX_SIZE] = { 0 };
|
||||
|
||||
mlxreg_hotplug_udev_envp[0] = event_str;
|
||||
string_upper(label, data->label);
|
||||
snprintf(event_str, MLXREG_CORE_LABEL_MAX_SIZE, "%s=%d", label, !!action);
|
||||
|
||||
return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp);
|
||||
}
|
||||
|
||||
static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
|
||||
struct mlxreg_core_data *data)
|
||||
{
|
||||
@ -104,7 +96,7 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
|
||||
struct i2c_client *client;
|
||||
|
||||
/* Notify user by sending hwmon uevent. */
|
||||
kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE);
|
||||
mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, true);
|
||||
|
||||
/*
|
||||
* Return if adapter number is negative. It could be in case hotplug
|
||||
@ -144,7 +136,7 @@ mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv,
|
||||
struct mlxreg_core_data *data)
|
||||
{
|
||||
/* Notify user by sending hwmon uevent. */
|
||||
kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE);
|
||||
mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, false);
|
||||
|
||||
if (data->hpdev.client) {
|
||||
i2c_unregister_device(data->hpdev.client);
|
||||
@ -199,17 +191,49 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
|
||||
struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
struct mlxreg_core_item *item;
|
||||
struct mlxreg_core_data *data;
|
||||
int num_attrs = 0, id = 0, i, j;
|
||||
unsigned long mask;
|
||||
u32 regval;
|
||||
int num_attrs = 0, id = 0, i, j, k, ret;
|
||||
|
||||
pdata = dev_get_platdata(&priv->pdev->dev);
|
||||
item = pdata->items;
|
||||
|
||||
/* Go over all kinds of items - psu, pwr, fan. */
|
||||
for (i = 0; i < pdata->counter; i++, item++) {
|
||||
num_attrs += item->count;
|
||||
if (item->capability) {
|
||||
/*
|
||||
* Read group capability register to get actual number
|
||||
* of interrupt capable components and set group mask
|
||||
* accordingly.
|
||||
*/
|
||||
ret = regmap_read(priv->regmap, item->capability,
|
||||
®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
item->mask = GENMASK((regval & item->mask) - 1, 0);
|
||||
}
|
||||
|
||||
data = item->data;
|
||||
/* Go over all units within the item. */
|
||||
for (j = 0; j < item->count; j++, data++, id++) {
|
||||
|
||||
/* Go over all unmasked units within item. */
|
||||
mask = item->mask;
|
||||
k = 0;
|
||||
for_each_set_bit(j, &mask, item->count) {
|
||||
if (data->capability) {
|
||||
/*
|
||||
* Read capability register and skip non
|
||||
* relevant attributes.
|
||||
*/
|
||||
ret = regmap_read(priv->regmap,
|
||||
data->capability, ®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!(regval & data->bit)) {
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PRIV_ATTR(id) = &PRIV_DEV_ATTR(id).dev_attr.attr;
|
||||
PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
|
||||
GFP_KERNEL,
|
||||
@ -227,9 +251,13 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
|
||||
PRIV_DEV_ATTR(id).dev_attr.show =
|
||||
mlxreg_hotplug_attr_show;
|
||||
PRIV_DEV_ATTR(id).nr = i;
|
||||
PRIV_DEV_ATTR(id).index = j;
|
||||
PRIV_DEV_ATTR(id).index = k;
|
||||
sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr);
|
||||
data++;
|
||||
id++;
|
||||
k++;
|
||||
}
|
||||
num_attrs += k;
|
||||
}
|
||||
|
||||
priv->group.attrs = devm_kcalloc(&priv->pdev->dev,
|
||||
@ -507,20 +535,6 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
|
||||
item = pdata->items;
|
||||
|
||||
for (i = 0; i < pdata->counter; i++, item++) {
|
||||
if (item->capability) {
|
||||
/*
|
||||
* Read group capability register to get actual number
|
||||
* of interrupt capable components and set group mask
|
||||
* accordingly.
|
||||
*/
|
||||
ret = regmap_read(priv->regmap, item->capability,
|
||||
®val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
item->mask = GENMASK((regval & item->mask) - 1, 0);
|
||||
}
|
||||
|
||||
/* Clear group presense event. */
|
||||
ret = regmap_write(priv->regmap, item->reg +
|
||||
MLXREG_HOTPLUG_EVENT_OFF, 0);
|
||||
|
@ -30,6 +30,7 @@
|
||||
* @mlxreg_io_dev_attr: sysfs sensor device attribute array;
|
||||
* @group: sysfs attribute group;
|
||||
* @groups: list of sysfs attribute group for hwmon registration;
|
||||
* @regsize: size of a register value;
|
||||
*/
|
||||
struct mlxreg_io_priv_data {
|
||||
struct platform_device *pdev;
|
||||
@ -39,27 +40,30 @@ struct mlxreg_io_priv_data {
|
||||
struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM];
|
||||
struct attribute_group group;
|
||||
const struct attribute_group *groups[2];
|
||||
int regsize;
|
||||
};
|
||||
|
||||
static int
|
||||
mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
|
||||
bool rw_flag, u32 *regval)
|
||||
bool rw_flag, int regsize, u32 *regval)
|
||||
{
|
||||
int ret;
|
||||
int i, val, ret;
|
||||
|
||||
ret = regmap_read(regmap, data->reg, regval);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
/*
|
||||
* There are three kinds of attributes: single bit, full register's
|
||||
* bits and bit sequence. For the first kind field mask indicates which
|
||||
* bits are not related and field bit is set zero. For the second kind
|
||||
* field mask is set to zero and field bit is set with all bits one.
|
||||
* No special handling for such kind of attributes - pass value as is.
|
||||
* For the third kind, field mask indicates which bits are related and
|
||||
* field bit is set to the first bit number (from 1 to 32) is the bit
|
||||
* sequence.
|
||||
* There are four kinds of attributes: single bit, full register's
|
||||
* bits, bit sequence, bits in few registers For the first kind field
|
||||
* mask indicates which bits are not related and field bit is set zero.
|
||||
* For the second kind field mask is set to zero and field bit is set
|
||||
* with all bits one. No special handling for such kind of attributes -
|
||||
* pass value as is. For the third kind, the field mask indicates which
|
||||
* bits are related and the field bit is set to the first bit number
|
||||
* (from 1 to 32) is the bit sequence. For the fourth kind - the number
|
||||
* of registers which should be read for getting an attribute are
|
||||
* specified through 'data->regnum' field.
|
||||
*/
|
||||
if (!data->bit) {
|
||||
/* Single bit. */
|
||||
@ -83,6 +87,19 @@ mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
|
||||
/* Clear relevant bits and set them to new value. */
|
||||
*regval = (*regval & ~data->mask) | in_val;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Some attributes could occupied few registers in case regmap
|
||||
* bit size is 8 or 16. Compose such attributes from 'regnum'
|
||||
* registers. Such attributes contain read-only data.
|
||||
*/
|
||||
for (i = 1; i < data->regnum; i++) {
|
||||
ret = regmap_read(regmap, data->reg + i, &val);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
*regval |= rol32(val, regsize * i);
|
||||
}
|
||||
}
|
||||
|
||||
access_error:
|
||||
@ -99,7 +116,8 @@ mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr,
|
||||
u32 regval = 0;
|
||||
int ret;
|
||||
|
||||
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, ®val);
|
||||
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true,
|
||||
priv->regsize, ®val);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
@ -128,7 +146,7 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr,
|
||||
return ret;
|
||||
|
||||
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false,
|
||||
®val);
|
||||
priv->regsize, ®val);
|
||||
if (ret)
|
||||
goto access_error;
|
||||
|
||||
@ -207,6 +225,9 @@ static int mlxreg_io_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
priv->pdev = pdev;
|
||||
priv->regsize = regmap_get_val_bytes(priv->pdata->regmap);
|
||||
if (priv->regsize < 0)
|
||||
return priv->regsize;
|
||||
|
||||
err = mlxreg_io_attr_init(priv);
|
||||
if (err) {
|
||||
|
@ -140,7 +140,7 @@ config ACERHDF
|
||||
in the same node directory will tell you if it is "acerhdf".
|
||||
|
||||
For more information about this driver see
|
||||
<http://piie.net/files/acerhdf_README.txt>
|
||||
<https://piie.net/files/acerhdf_README.txt>
|
||||
|
||||
If you have an Acer Aspire One netbook, say Y or M
|
||||
here.
|
||||
@ -748,6 +748,27 @@ config THINKPAD_ACPI_HOTKEY_POLL
|
||||
If you are not sure, say Y here. The driver enables polling only if
|
||||
it is strictly necessary to do so.
|
||||
|
||||
config INTEL_ATOMISP2_LED
|
||||
tristate "Intel AtomISP2 camera LED driver"
|
||||
depends on GPIOLIB && LEDS_GPIO
|
||||
help
|
||||
Many Bay Trail and Cherry Trail devices come with a camera attached
|
||||
to Intel's Image Signal Processor. Linux currently does not have a
|
||||
driver for these, so they do not work as a camera. Some of these
|
||||
camera's have a LED which is controlled through a GPIO.
|
||||
|
||||
Some of these devices have a firmware issue where the LED gets turned
|
||||
on at boot. This driver will turn the LED off at boot and also allows
|
||||
controlling the LED (repurposing it) through the sysfs LED interface.
|
||||
|
||||
Which GPIO is attached to the LED is usually not described in the
|
||||
ACPI tables, so this driver contains per-system info about the GPIO
|
||||
inside the driver, this means that this driver only works on systems
|
||||
the driver knows about.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called intel_atomisp2_led.
|
||||
|
||||
config INTEL_ATOMISP2_PM
|
||||
tristate "Intel AtomISP2 dummy / power-management driver"
|
||||
depends on PCI && IOSF_MBI && PM
|
||||
|
@ -69,6 +69,7 @@ obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
|
||||
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
|
||||
|
||||
# Intel
|
||||
obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o
|
||||
obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
|
||||
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
|
||||
intel_cht_int33fe-objs := intel_cht_int33fe_common.o \
|
||||
|
@ -5,7 +5,7 @@
|
||||
* as soon as the upper/lower threshold is reached.
|
||||
*
|
||||
* (C) 2009 - Peter Kaestle peter (a) piie.net
|
||||
* http://piie.net
|
||||
* https://piie.net
|
||||
* 2009 Borislav Petkov bp (a) alien8.de
|
||||
*
|
||||
* Inspired by and many thanks to:
|
||||
|
@ -277,8 +277,8 @@ static bool gmux_is_indexed(struct apple_gmux_data *gmux_data)
|
||||
* MBP5 2008/09 uses a `TI LP8543`_ backlight driver. All newer models
|
||||
* use a `TI LP8545`_.
|
||||
*
|
||||
* .. _TI LP8543: http://www.ti.com/lit/ds/symlink/lp8543.pdf
|
||||
* .. _TI LP8545: http://www.ti.com/lit/ds/symlink/lp8545.pdf
|
||||
* .. _TI LP8543: https://www.ti.com/lit/ds/symlink/lp8543.pdf
|
||||
* .. _TI LP8545: https://www.ti.com/lit/ds/symlink/lp8545.pdf
|
||||
*/
|
||||
|
||||
static int gmux_get_brightness(struct backlight_device *bd)
|
||||
@ -373,14 +373,14 @@ static const struct backlight_ops gmux_bl_ops = {
|
||||
* switch the panel and the external DP connector and allocates a framebuffer
|
||||
* for the selected GPU.
|
||||
*
|
||||
* .. _US 8,687,007 B2: http://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf
|
||||
* .. _NXP CBTL06141: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
||||
* .. _NXP CBTL06142: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
||||
* .. _TI HD3SS212: http://www.ti.com/lit/ds/symlink/hd3ss212.pdf
|
||||
* .. _US 8,687,007 B2: https://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf
|
||||
* .. _NXP CBTL06141: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
||||
* .. _NXP CBTL06142: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
||||
* .. _TI HD3SS212: https://www.ti.com/lit/ds/symlink/hd3ss212.pdf
|
||||
* .. _Pericom PI3VDP12412: https://www.pericom.com/assets/Datasheets/PI3VDP12412.pdf
|
||||
* .. _TI SN74LV4066A: http://www.ti.com/lit/ds/symlink/sn74lv4066a.pdf
|
||||
* .. _TI SN74LV4066A: https://www.ti.com/lit/ds/symlink/sn74lv4066a.pdf
|
||||
* .. _NXP CBTL03062: http://pdf.datasheetarchive.com/indexerfiles/Datasheets-SW16/DSASW00308511.pdf
|
||||
* .. _TI TS3DS10224: http://www.ti.com/lit/ds/symlink/ts3ds10224.pdf
|
||||
* .. _TI TS3DS10224: https://www.ti.com/lit/ds/symlink/ts3ds10224.pdf
|
||||
*/
|
||||
|
||||
static void gmux_read_switch_state(struct apple_gmux_data *gmux_data)
|
||||
|
@ -110,6 +110,11 @@ static struct quirk_entry quirk_asus_forceals = {
|
||||
.wmi_force_als_set = true,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_asus_vendor_backlight = {
|
||||
.wmi_backlight_power = true,
|
||||
.wmi_backlight_set_devstate = true,
|
||||
};
|
||||
|
||||
static int dmi_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
pr_info("Identified laptop model '%s'\n", dmi->ident);
|
||||
@ -411,6 +416,78 @@ static const struct dmi_system_id asus_quirks[] = {
|
||||
},
|
||||
.driver_data = &quirk_asus_forceals,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA401IH",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA401IH"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA401II",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA401II"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA401IU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA401IU"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA401IV",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA401IV"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA401IVC",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA401IVC"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA502II",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA502II"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA502IU",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA502IU"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
.ident = "ASUSTeK COMPUTER INC. GA502IV",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GA502IV"),
|
||||
},
|
||||
.driver_data = &quirk_asus_vendor_backlight,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
@ -255,6 +255,10 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = {
|
||||
/* Keyboard backlight change notification */
|
||||
{ KE_IGNORE, 0x3f, { KEY_RESERVED } },
|
||||
|
||||
/* Backlight brightness level */
|
||||
{ KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } },
|
||||
{ KE_KEY, 0x58, { KEY_BRIGHTNESSUP } },
|
||||
|
||||
/* Mic mute */
|
||||
{ KE_KEY, 0x150, { KEY_MICMUTE } },
|
||||
|
||||
@ -330,6 +334,15 @@ static const struct key_entry dell_wmi_keymap_type_0011[] = {
|
||||
{ KE_IGNORE, KBD_LED_AUTO_100_TOKEN, { KEY_RESERVED } },
|
||||
};
|
||||
|
||||
/*
|
||||
* Keymap for WMI events of type 0x0012
|
||||
* They are events with extended data
|
||||
*/
|
||||
static const struct key_entry dell_wmi_keymap_type_0012[] = {
|
||||
/* Fn-lock button pressed */
|
||||
{ KE_IGNORE, 0xe035, { KEY_RESERVED } },
|
||||
};
|
||||
|
||||
static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code)
|
||||
{
|
||||
struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
|
||||
@ -414,10 +427,11 @@ static void dell_wmi_notify(struct wmi_device *wdev,
|
||||
|
||||
switch (buffer_entry[1]) {
|
||||
case 0x0000: /* One key pressed or event occurred */
|
||||
case 0x0012: /* Event with extended data occurred */
|
||||
if (len > 2)
|
||||
dell_wmi_process_key(wdev, 0x0000,
|
||||
dell_wmi_process_key(wdev, buffer_entry[1],
|
||||
buffer_entry[2]);
|
||||
/* Other entries could contain additional information */
|
||||
/* Extended data is currently ignored */
|
||||
break;
|
||||
case 0x0010: /* Sequence of keys pressed */
|
||||
case 0x0011: /* Sequence of events occurred */
|
||||
@ -492,7 +506,7 @@ static void handle_dmi_entry(const struct dmi_header *dm, void *opaque)
|
||||
u16 keycode = (bios_entry->keycode <
|
||||
ARRAY_SIZE(bios_to_linux_keycode)) ?
|
||||
bios_to_linux_keycode[bios_entry->keycode] :
|
||||
KEY_RESERVED;
|
||||
(bios_entry->keycode == 0xffff ? KEY_UNKNOWN : KEY_RESERVED);
|
||||
|
||||
/*
|
||||
* Log if we find an entry in the DMI table that we don't
|
||||
@ -552,6 +566,7 @@ static int dell_wmi_input_setup(struct wmi_device *wdev)
|
||||
ARRAY_SIZE(dell_wmi_keymap_type_0000) +
|
||||
ARRAY_SIZE(dell_wmi_keymap_type_0010) +
|
||||
ARRAY_SIZE(dell_wmi_keymap_type_0011) +
|
||||
ARRAY_SIZE(dell_wmi_keymap_type_0012) +
|
||||
1,
|
||||
sizeof(struct key_entry), GFP_KERNEL);
|
||||
if (!keymap) {
|
||||
@ -596,6 +611,13 @@ static int dell_wmi_input_setup(struct wmi_device *wdev)
|
||||
pos++;
|
||||
}
|
||||
|
||||
/* Append table with events of type 0x0012 */
|
||||
for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
|
||||
keymap[pos] = dell_wmi_keymap_type_0012[i];
|
||||
keymap[pos].code |= (0x0012 << 16);
|
||||
pos++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now append also table with "legacy" events of type 0x0000. Some of
|
||||
* them are reported also on laptops which have scancodes in DMI.
|
||||
|
@ -571,7 +571,7 @@ check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
return AE_OK;
|
||||
|
||||
if (acpi_match_device_ids(dev, ids) == 0)
|
||||
if (acpi_create_platform_device(dev, NULL))
|
||||
if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL)))
|
||||
dev_info(&dev->dev,
|
||||
"intel-hid: created platform device\n");
|
||||
|
||||
|
@ -299,7 +299,7 @@ check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
return AE_OK;
|
||||
|
||||
if (acpi_match_device_ids(dev, ids) == 0)
|
||||
if (acpi_create_platform_device(dev, NULL))
|
||||
if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL)))
|
||||
dev_info(&dev->dev,
|
||||
"intel-vbtn: created platform device\n");
|
||||
|
||||
|
116
drivers/platform/x86/intel_atomisp2_led.c
Normal file
116
drivers/platform/x86/intel_atomisp2_led.c
Normal file
@ -0,0 +1,116 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Driver for controlling LEDs for cameras connected to the Intel atomisp2
|
||||
* The main purpose of this driver is to turn off LEDs which are on at boot.
|
||||
*
|
||||
* Copyright (C) 2020 Hans de Goede <hdegoede@redhat.com>
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/* This must be leds-gpio as the leds-gpio driver binds to the name */
|
||||
#define DEV_NAME "leds-gpio"
|
||||
|
||||
static const struct gpio_led atomisp2_leds[] = {
|
||||
{
|
||||
.name = "atomisp2::camera",
|
||||
.default_state = LEDS_GPIO_DEFSTATE_OFF,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct gpio_led_platform_data atomisp2_leds_pdata = {
|
||||
.num_leds = ARRAY_SIZE(atomisp2_leds),
|
||||
.leds = atomisp2_leds,
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table asus_t100ta_lookup = {
|
||||
.dev_id = DEV_NAME,
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("INT33FC:02", 8, NULL, 0, GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table asus_t100chi_lookup = {
|
||||
.dev_id = DEV_NAME,
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("INT33FC:01", 24, NULL, 0, GPIO_ACTIVE_HIGH),
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
static const struct dmi_system_id atomisp2_led_systems[] __initconst = {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
|
||||
},
|
||||
.driver_data = &asus_t100ta_lookup,
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"),
|
||||
},
|
||||
.driver_data = &asus_t100ta_lookup,
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"),
|
||||
},
|
||||
.driver_data = &asus_t100chi_lookup,
|
||||
},
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, atomisp2_led_systems);
|
||||
|
||||
static struct gpiod_lookup_table *gpio_lookup;
|
||||
static struct platform_device *pdev;
|
||||
|
||||
static int __init atomisp2_led_init(void)
|
||||
{
|
||||
const struct dmi_system_id *system;
|
||||
|
||||
system = dmi_first_match(atomisp2_led_systems);
|
||||
if (!system)
|
||||
return -ENODEV;
|
||||
|
||||
gpio_lookup = system->driver_data;
|
||||
gpiod_add_lookup_table(gpio_lookup);
|
||||
|
||||
pdev = platform_device_register_resndata(NULL,
|
||||
DEV_NAME, PLATFORM_DEVID_NONE,
|
||||
NULL, 0, &atomisp2_leds_pdata,
|
||||
sizeof(atomisp2_leds_pdata));
|
||||
if (IS_ERR(pdev))
|
||||
gpiod_remove_lookup_table(gpio_lookup);
|
||||
|
||||
return PTR_ERR_OR_ZERO(pdev);
|
||||
}
|
||||
|
||||
static void __exit atomisp2_led_cleanup(void)
|
||||
{
|
||||
platform_device_unregister(pdev);
|
||||
gpiod_remove_lookup_table(gpio_lookup);
|
||||
}
|
||||
|
||||
module_init(atomisp2_led_init);
|
||||
module_exit(atomisp2_led_cleanup);
|
||||
|
||||
/*
|
||||
* The ACPI INIT method from Asus WMI's code on the T100TA and T200TA turns the
|
||||
* LED on (without the WMI interface allowing further control over the LED).
|
||||
* Ensure we are loaded after asus-nb-wmi so that we turn the LED off again.
|
||||
*/
|
||||
MODULE_SOFTDEP("pre: asus_nb_wmi");
|
||||
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com");
|
||||
MODULE_DESCRIPTION("Intel atomisp2 camera LED driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -29,18 +29,16 @@ static int cht_int33fe_i2c_res_filter(struct acpi_resource *ares, void *data)
|
||||
|
||||
static int cht_int33fe_count_i2c_clients(struct device *dev)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
LIST_HEAD(resource_list);
|
||||
int count = 0;
|
||||
int ret;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (!adev)
|
||||
return -EINVAL;
|
||||
|
||||
acpi_dev_get_resources(adev, &resource_list,
|
||||
cht_int33fe_i2c_res_filter, &count);
|
||||
|
||||
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||
cht_int33fe_i2c_res_filter, &count);
|
||||
acpi_dev_free_resource_list(&resource_list);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -415,7 +415,7 @@ static const struct pmc_bit_map tgl_lpm0_map[] = {
|
||||
{"PCIe_Gen3PLL_OFF_STS", BIT(20)},
|
||||
{"OPIOPLL_OFF_STS", BIT(21)},
|
||||
{"OCPLL_OFF_STS", BIT(22)},
|
||||
{"AudioPLL_OFF_STS", BIT(23)},
|
||||
{"MainPLL_OFF_STS", BIT(23)},
|
||||
{"MIPIPLL_OFF_STS", BIT(24)},
|
||||
{"Fast_XTAL_Osc_OFF_STS", BIT(25)},
|
||||
{"AC_Ring_Osc_OFF_STS", BIT(26)},
|
||||
@ -795,7 +795,7 @@ static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused)
|
||||
msleep(10);
|
||||
val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET);
|
||||
|
||||
for (index = 0; map[index].name && index < 8; index++) {
|
||||
for (index = 0; index < 8 && map[index].name; index++) {
|
||||
seq_printf(s, "%-32s\tState: %s\n",
|
||||
map[index].name,
|
||||
map[index].bit_mask & val_low ? "Not power gated" :
|
||||
|
@ -26,6 +26,10 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET 0x04
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET 0x06
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET 0x08
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET 0x0a
|
||||
#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d
|
||||
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e
|
||||
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f
|
||||
@ -72,6 +76,10 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET 0xe1
|
||||
#define MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET 0xe2
|
||||
#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
|
||||
@ -1303,6 +1311,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld1_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld2_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld1_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld2_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "reset_long_pb",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
@ -1409,6 +1443,32 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = {
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld1_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld2_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld1_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld2_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "reset_long_pb",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
@ -1527,6 +1587,58 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld1_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld2_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld3_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld4_pn",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET,
|
||||
.bit = GENMASK(15, 0),
|
||||
.mode = 0444,
|
||||
.regnum = 2,
|
||||
},
|
||||
{
|
||||
.label = "cpld1_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld2_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld3_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "cpld4_version_min",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET,
|
||||
.bit = GENMASK(7, 0),
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
.label = "reset_long_pb",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
@ -1728,6 +1840,8 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(0),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
|
||||
},
|
||||
{
|
||||
.label = "tacho2",
|
||||
@ -1735,6 +1849,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(1),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho3",
|
||||
@ -1742,6 +1857,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(2),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho4",
|
||||
@ -1749,6 +1865,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(3),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho5",
|
||||
@ -1756,6 +1873,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(4),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho6",
|
||||
@ -1763,6 +1881,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(5),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho7",
|
||||
@ -1770,6 +1889,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(6),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho8",
|
||||
@ -1777,6 +1897,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||
.bit = BIT(7),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho9",
|
||||
@ -1784,6 +1905,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||
.bit = BIT(0),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho10",
|
||||
@ -1791,6 +1913,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||
.bit = BIT(1),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho11",
|
||||
@ -1798,6 +1921,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||
.bit = BIT(2),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "tacho12",
|
||||
@ -1805,6 +1929,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
.mask = GENMASK(7, 0),
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||
.bit = BIT(3),
|
||||
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||
},
|
||||
{
|
||||
.label = "conf",
|
||||
@ -2006,6 +2131,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
|
||||
@ -2051,6 +2180,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@ -2085,6 +2218,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
|
||||
@ -2122,6 +2259,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
|
@ -78,7 +78,6 @@ static const struct gpio_led apu2_leds[] = {
|
||||
{ .name = "apu:green:1" },
|
||||
{ .name = "apu:green:2" },
|
||||
{ .name = "apu:green:3" },
|
||||
{ .name = "apu:simswap" },
|
||||
};
|
||||
|
||||
static const struct gpio_led_platform_data apu2_leds_pdata = {
|
||||
@ -95,8 +94,6 @@ static struct gpiod_lookup_table gpios_led_table = {
|
||||
NULL, 1, GPIO_ACTIVE_LOW),
|
||||
GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
|
||||
NULL, 2, GPIO_ACTIVE_LOW),
|
||||
GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_SIMSWAP,
|
||||
NULL, 3, GPIO_ACTIVE_LOW),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -103,12 +103,12 @@ static enum led_brightness ap_led_get(struct led_classdev *led)
|
||||
}
|
||||
|
||||
// Set the airplane mode LED brightness
|
||||
static void ap_led_set(struct led_classdev *led, enum led_brightness value)
|
||||
static int 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);
|
||||
return system76_set(data, "SAPL", value == LED_OFF ? 0 : 1);
|
||||
}
|
||||
|
||||
// Get the last set keyboard LED brightness
|
||||
@ -121,13 +121,13 @@ static enum led_brightness kb_led_get(struct led_classdev *led)
|
||||
}
|
||||
|
||||
// Set the keyboard LED brightness
|
||||
static void kb_led_set(struct led_classdev *led, enum led_brightness value)
|
||||
static int 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);
|
||||
return system76_set(data, "SKBL", (int)data->kb_brightness);
|
||||
}
|
||||
|
||||
// Get the last set keyboard LED color
|
||||
@ -313,7 +313,7 @@ static int system76_add(struct acpi_device *acpi_dev)
|
||||
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.brightness_set_blocking = 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);
|
||||
@ -323,7 +323,7 @@ static int system76_add(struct acpi_device *acpi_dev)
|
||||
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;
|
||||
data->kb_led.brightness_set_blocking = 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;
|
||||
|
@ -4030,8 +4030,8 @@ static bool hotkey_notify_6xxx(const u32 hkey,
|
||||
return true;
|
||||
case TP_HKEY_EV_THM_CSM_COMPLETED:
|
||||
pr_debug("EC reports: Thermal Control Command set completed (DYTC)\n");
|
||||
/* recommended action: do nothing, we don't have
|
||||
* Lenovo ATM information */
|
||||
/* Thermal event - pass on to event handler */
|
||||
tpacpi_driver_event(hkey);
|
||||
return true;
|
||||
case TP_HKEY_EV_THM_TRANSFM_CHANGED:
|
||||
pr_debug("EC reports: Thermal Transformation changed (GMTS)\n");
|
||||
@ -6963,10 +6963,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
|
||||
pr_warn("Cannot enable backlight brightness support, ACPI is already handling it. Refer to the acpi_backlight kernel parameter.\n");
|
||||
return 1;
|
||||
}
|
||||
} else if (tp_features.bright_acpimode && brightness_enable > 1) {
|
||||
pr_notice("Standard ACPI backlight interface not available, thinkpad_acpi native brightness control enabled\n");
|
||||
} else if (!tp_features.bright_acpimode) {
|
||||
pr_notice("ACPI backlight interface not available\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pr_notice("ACPI native brightness control enabled\n");
|
||||
|
||||
/*
|
||||
* Check for module parameter bogosity, note that we
|
||||
* init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be
|
||||
@ -7965,7 +7968,7 @@ static struct ibm_struct volume_driver_data = {
|
||||
* does so, its initial value is meaningless (0x07).
|
||||
*
|
||||
* For firmware bugs, refer to:
|
||||
* http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
|
||||
* https://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
|
||||
*
|
||||
* ----
|
||||
*
|
||||
@ -7990,7 +7993,7 @@ static struct ibm_struct volume_driver_data = {
|
||||
* mode.
|
||||
*
|
||||
* For firmware bugs, refer to:
|
||||
* http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
|
||||
* https://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
|
||||
*
|
||||
* ----
|
||||
*
|
||||
@ -9315,9 +9318,6 @@ static struct ibm_struct mute_led_driver_data = {
|
||||
#define GET_STOP "BCSG"
|
||||
#define SET_STOP "BCSS"
|
||||
|
||||
#define START_ATTR "charge_start_threshold"
|
||||
#define STOP_ATTR "charge_stop_threshold"
|
||||
|
||||
enum {
|
||||
BAT_ANY = 0,
|
||||
BAT_PRIMARY = 1,
|
||||
@ -9603,38 +9603,52 @@ static ssize_t tpacpi_battery_show(int what,
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t charge_start_threshold_show(struct device *device,
|
||||
static ssize_t charge_control_start_threshold_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return tpacpi_battery_show(THRESHOLD_START, device, buf);
|
||||
}
|
||||
|
||||
static ssize_t charge_stop_threshold_show(struct device *device,
|
||||
static ssize_t charge_control_end_threshold_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return tpacpi_battery_show(THRESHOLD_STOP, device, buf);
|
||||
}
|
||||
|
||||
static ssize_t charge_start_threshold_store(struct device *dev,
|
||||
static ssize_t charge_control_start_threshold_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return tpacpi_battery_store(THRESHOLD_START, dev, buf, count);
|
||||
}
|
||||
|
||||
static ssize_t charge_stop_threshold_store(struct device *dev,
|
||||
static ssize_t charge_control_end_threshold_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
return tpacpi_battery_store(THRESHOLD_STOP, dev, buf, count);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(charge_start_threshold);
|
||||
static DEVICE_ATTR_RW(charge_stop_threshold);
|
||||
static DEVICE_ATTR_RW(charge_control_start_threshold);
|
||||
static DEVICE_ATTR_RW(charge_control_end_threshold);
|
||||
static struct device_attribute dev_attr_charge_start_threshold = __ATTR(
|
||||
charge_start_threshold,
|
||||
0644,
|
||||
charge_control_start_threshold_show,
|
||||
charge_control_start_threshold_store
|
||||
);
|
||||
static struct device_attribute dev_attr_charge_stop_threshold = __ATTR(
|
||||
charge_stop_threshold,
|
||||
0644,
|
||||
charge_control_end_threshold_show,
|
||||
charge_control_end_threshold_store
|
||||
);
|
||||
|
||||
static struct attribute *tpacpi_battery_attrs[] = {
|
||||
&dev_attr_charge_control_start_threshold.attr,
|
||||
&dev_attr_charge_control_end_threshold.attr,
|
||||
&dev_attr_charge_start_threshold.attr,
|
||||
&dev_attr_charge_stop_threshold.attr,
|
||||
NULL,
|
||||
@ -9803,6 +9817,105 @@ static struct ibm_struct lcdshadow_driver_data = {
|
||||
.write = lcdshadow_write,
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* DYTC subdriver, for the Lenovo lapmode feature
|
||||
*/
|
||||
|
||||
#define DYTC_CMD_GET 2 /* To get current IC function and mode */
|
||||
#define DYTC_GET_LAPMODE_BIT 17 /* Set when in lapmode */
|
||||
|
||||
static bool dytc_lapmode;
|
||||
|
||||
static void dytc_lapmode_notify_change(void)
|
||||
{
|
||||
sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "dytc_lapmode");
|
||||
}
|
||||
|
||||
static int dytc_command(int command, int *output)
|
||||
{
|
||||
acpi_handle dytc_handle;
|
||||
|
||||
if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle))) {
|
||||
/* Platform doesn't support DYTC */
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!acpi_evalf(dytc_handle, output, NULL, "dd", command))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dytc_lapmode_get(bool *state)
|
||||
{
|
||||
int output, err;
|
||||
|
||||
err = dytc_command(DYTC_CMD_GET, &output);
|
||||
if (err)
|
||||
return err;
|
||||
*state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dytc_lapmode_refresh(void)
|
||||
{
|
||||
bool new_state;
|
||||
int err;
|
||||
|
||||
err = dytc_lapmode_get(&new_state);
|
||||
if (err || (new_state == dytc_lapmode))
|
||||
return;
|
||||
|
||||
dytc_lapmode = new_state;
|
||||
dytc_lapmode_notify_change();
|
||||
}
|
||||
|
||||
/* sysfs lapmode entry */
|
||||
static ssize_t dytc_lapmode_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", dytc_lapmode);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(dytc_lapmode);
|
||||
|
||||
static struct attribute *dytc_attributes[] = {
|
||||
&dev_attr_dytc_lapmode.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group dytc_attr_group = {
|
||||
.attrs = dytc_attributes,
|
||||
};
|
||||
|
||||
static int tpacpi_dytc_init(struct ibm_init_struct *iibm)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = dytc_lapmode_get(&dytc_lapmode);
|
||||
/* If support isn't available (ENODEV) then don't return an error
|
||||
* but just don't create the sysfs group
|
||||
*/
|
||||
if (err == -ENODEV)
|
||||
return 0;
|
||||
/* For all other errors we can flag the failure */
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Platform supports this feature - create the group */
|
||||
err = sysfs_create_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void dytc_exit(void)
|
||||
{
|
||||
sysfs_remove_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
|
||||
}
|
||||
|
||||
static struct ibm_struct dytc_driver_data = {
|
||||
.name = "dytc",
|
||||
.exit = dytc_exit,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
****************************************************************************
|
||||
*
|
||||
@ -9850,6 +9963,10 @@ static void tpacpi_driver_event(const unsigned int hkey_event)
|
||||
|
||||
mutex_unlock(&kbdlight_mutex);
|
||||
}
|
||||
|
||||
if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED)
|
||||
dytc_lapmode_refresh();
|
||||
|
||||
}
|
||||
|
||||
static void hotkey_driver_event(const unsigned int scancode)
|
||||
@ -10102,7 +10219,7 @@ static int __must_check __init get_thinkpad_model_data(
|
||||
* X32 or newer, all Z series; Some models must have an
|
||||
* up-to-date BIOS or they will not be detected.
|
||||
*
|
||||
* See http://thinkwiki.org/wiki/List_of_DMI_IDs
|
||||
* See https://thinkwiki.org/wiki/List_of_DMI_IDs
|
||||
*/
|
||||
while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
|
||||
if (sscanf(dev->name,
|
||||
@ -10288,6 +10405,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
|
||||
.init = tpacpi_lcdshadow_init,
|
||||
.data = &lcdshadow_driver_data,
|
||||
},
|
||||
{
|
||||
.init = tpacpi_dytc_init,
|
||||
.data = &dytc_driver_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init set_ibm_param(const char *val, const struct kernel_param *kp)
|
||||
@ -10621,8 +10742,8 @@ MODULE_DEVICE_TABLE(acpi, ibm_htk_device_ids);
|
||||
/*
|
||||
* DMI matching for module autoloading
|
||||
*
|
||||
* See http://thinkwiki.org/wiki/List_of_DMI_IDs
|
||||
* See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
|
||||
* See https://thinkwiki.org/wiki/List_of_DMI_IDs
|
||||
* See https://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
|
||||
*
|
||||
* Only models listed in thinkwiki will be supported, so add yours
|
||||
* if it is not there yet.
|
||||
|
@ -75,11 +75,13 @@ struct mlxreg_hotplug_device {
|
||||
* @mask: attribute access mask;
|
||||
* @bit: attribute effective bit;
|
||||
* @capability: attribute capability register;
|
||||
* @reg_prsnt: attribute presence register;
|
||||
* @mode: access mode;
|
||||
* @np - pointer to node platform associated with attribute;
|
||||
* @hpdev - hotplug device data;
|
||||
* @health_cntr: dynamic device health indication counter;
|
||||
* @attached: true if device has been attached after good health indication;
|
||||
* @regnum: number of registers occupied by multi-register attribute;
|
||||
*/
|
||||
struct mlxreg_core_data {
|
||||
char label[MLXREG_CORE_LABEL_MAX_SIZE];
|
||||
@ -87,11 +89,13 @@ struct mlxreg_core_data {
|
||||
u32 mask;
|
||||
u32 bit;
|
||||
u32 capability;
|
||||
u32 reg_prsnt;
|
||||
umode_t mode;
|
||||
struct device_node *np;
|
||||
struct mlxreg_hotplug_device hpdev;
|
||||
u8 health_cntr;
|
||||
bool attached;
|
||||
u8 regnum;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef _LINUX_STRING_HELPERS_H_
|
||||
#define _LINUX_STRING_HELPERS_H_
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct file;
|
||||
@ -75,6 +76,20 @@ static inline int string_escape_str_any_np(const char *src, char *dst,
|
||||
return string_escape_str(src, dst, sz, ESCAPE_ANY_NP, only);
|
||||
}
|
||||
|
||||
static inline void string_upper(char *dst, const char *src)
|
||||
{
|
||||
do {
|
||||
*dst++ = toupper(*src);
|
||||
} while (*src++);
|
||||
}
|
||||
|
||||
static inline void string_lower(char *dst, const char *src)
|
||||
{
|
||||
do {
|
||||
*dst++ = tolower(*src);
|
||||
} while (*src++);
|
||||
}
|
||||
|
||||
char *kstrdup_quotable(const char *src, gfp_t gfp);
|
||||
char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp);
|
||||
char *kstrdup_quotable_file(struct file *file, gfp_t gfp);
|
||||
|
@ -69,7 +69,7 @@ struct isst_if_cpu_maps {
|
||||
* @logical_cpu: Logical CPU number to get target PCI device.
|
||||
* @reg: PUNIT register offset
|
||||
* @value: For write operation value to write and for
|
||||
* for read placeholder read value
|
||||
* read placeholder read value
|
||||
*
|
||||
* Structure to specify read/write data to PUNIT registers.
|
||||
*/
|
||||
|
@ -238,6 +238,28 @@ static const struct test_string_2 escape1[] __initconst = {{
|
||||
/* terminator */
|
||||
}};
|
||||
|
||||
static const struct test_string strings_upper[] __initconst = {
|
||||
{
|
||||
.in = "abcdefgh1234567890test",
|
||||
.out = "ABCDEFGH1234567890TEST",
|
||||
},
|
||||
{
|
||||
.in = "abCdeFgH1234567890TesT",
|
||||
.out = "ABCDEFGH1234567890TEST",
|
||||
},
|
||||
};
|
||||
|
||||
static const struct test_string strings_lower[] __initconst = {
|
||||
{
|
||||
.in = "ABCDEFGH1234567890TEST",
|
||||
.out = "abcdefgh1234567890test",
|
||||
},
|
||||
{
|
||||
.in = "abCdeFgH1234567890TesT",
|
||||
.out = "abcdefgh1234567890test",
|
||||
},
|
||||
};
|
||||
|
||||
static __init const char *test_string_find_match(const struct test_string_2 *s2,
|
||||
unsigned int flags)
|
||||
{
|
||||
@ -390,6 +412,48 @@ static __init void test_string_get_size(void)
|
||||
test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB");
|
||||
}
|
||||
|
||||
static void __init test_string_upper_lower(void)
|
||||
{
|
||||
char *dst;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(strings_upper); i++) {
|
||||
const char *s = strings_upper[i].in;
|
||||
int len = strlen(strings_upper[i].in) + 1;
|
||||
|
||||
dst = kmalloc(len, GFP_KERNEL);
|
||||
if (!dst)
|
||||
return;
|
||||
|
||||
string_upper(dst, s);
|
||||
if (memcmp(dst, strings_upper[i].out, len)) {
|
||||
pr_warn("Test 'string_upper' failed : expected %s, got %s!\n",
|
||||
strings_upper[i].out, dst);
|
||||
kfree(dst);
|
||||
return;
|
||||
}
|
||||
kfree(dst);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(strings_lower); i++) {
|
||||
const char *s = strings_lower[i].in;
|
||||
int len = strlen(strings_lower[i].in) + 1;
|
||||
|
||||
dst = kmalloc(len, GFP_KERNEL);
|
||||
if (!dst)
|
||||
return;
|
||||
|
||||
string_lower(dst, s);
|
||||
if (memcmp(dst, strings_lower[i].out, len)) {
|
||||
pr_warn("Test 'string_lower failed : : expected %s, got %s!\n",
|
||||
strings_lower[i].out, dst);
|
||||
kfree(dst);
|
||||
return;
|
||||
}
|
||||
kfree(dst);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init test_string_helpers_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -411,6 +475,9 @@ static int __init test_string_helpers_init(void)
|
||||
/* Test string_get_size() */
|
||||
test_string_get_size();
|
||||
|
||||
/* Test string upper(), string_lower() */
|
||||
test_string_upper_lower();
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
module_init(test_string_helpers_init);
|
||||
|
@ -15,7 +15,7 @@ struct process_cmd_struct {
|
||||
int arg;
|
||||
};
|
||||
|
||||
static const char *version_str = "v1.4";
|
||||
static const char *version_str = "v1.5";
|
||||
static const int supported_api_ver = 1;
|
||||
static struct isst_if_platform_info isst_platform_info;
|
||||
static char *progname;
|
||||
@ -44,6 +44,9 @@ static int force_online_offline;
|
||||
static int auto_mode;
|
||||
static int fact_enable_fail;
|
||||
|
||||
static int mbox_delay;
|
||||
static int mbox_retries = 3;
|
||||
|
||||
/* clos related */
|
||||
static int current_clos = -1;
|
||||
static int clos_epp = -1;
|
||||
@ -198,7 +201,7 @@ int out_format_is_json(void)
|
||||
|
||||
static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
|
||||
{
|
||||
const char *pathname = "/tmp/isst_cpu_topology.dat";
|
||||
const char *pathname = "/var/run/isst_cpu_topology.dat";
|
||||
struct cpu_topology cpu_top;
|
||||
FILE *fp;
|
||||
int ret;
|
||||
@ -230,7 +233,7 @@ static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die
|
||||
|
||||
static void store_cpu_topology(void)
|
||||
{
|
||||
const char *pathname = "/tmp/isst_cpu_topology.dat";
|
||||
const char *pathname = "/var/run/isst_cpu_topology.dat";
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
@ -247,6 +250,8 @@ static void store_cpu_topology(void)
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Caching topology information\n");
|
||||
|
||||
for (i = 0; i < topo_max_cpus; ++i) {
|
||||
struct cpu_topology cpu_top;
|
||||
|
||||
@ -734,7 +739,7 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command,
|
||||
unsigned int req_data, unsigned int *resp)
|
||||
{
|
||||
const char *pathname = "/dev/isst_interface";
|
||||
int fd;
|
||||
int fd, retry;
|
||||
struct isst_if_mbox_cmds mbox_cmds = { 0 };
|
||||
|
||||
debug_printf(
|
||||
@ -786,29 +791,42 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command,
|
||||
mbox_cmds.mbox_cmd[0].parameter = parameter;
|
||||
mbox_cmds.mbox_cmd[0].req_data = req_data;
|
||||
|
||||
if (mbox_delay)
|
||||
usleep(mbox_delay * 1000);
|
||||
|
||||
fd = open(pathname, O_RDWR);
|
||||
if (fd < 0)
|
||||
err(-1, "%s open failed", pathname);
|
||||
|
||||
if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
|
||||
if (errno == ENOTTY) {
|
||||
perror("ISST_IF_MBOX_COMMAND\n");
|
||||
fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
|
||||
exit(0);
|
||||
retry = mbox_retries;
|
||||
|
||||
do {
|
||||
if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
|
||||
if (errno == ENOTTY) {
|
||||
perror("ISST_IF_MBOX_COMMAND\n");
|
||||
fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
|
||||
exit(0);
|
||||
}
|
||||
debug_printf(
|
||||
"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
|
||||
cpu, command, sub_command, parameter, req_data, errno);
|
||||
--retry;
|
||||
} else {
|
||||
*resp = mbox_cmds.mbox_cmd[0].resp_data;
|
||||
debug_printf(
|
||||
"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
|
||||
cpu, command, sub_command, parameter, req_data, *resp);
|
||||
break;
|
||||
}
|
||||
debug_printf(
|
||||
"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
|
||||
cpu, command, sub_command, parameter, req_data, errno);
|
||||
return -1;
|
||||
} else {
|
||||
*resp = mbox_cmds.mbox_cmd[0].resp_data;
|
||||
debug_printf(
|
||||
"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
|
||||
cpu, command, sub_command, parameter, req_data, *resp);
|
||||
}
|
||||
} while (retry);
|
||||
|
||||
close(fd);
|
||||
|
||||
if (!retry) {
|
||||
debug_printf("Failed mbox command even after retries\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1245,7 +1263,11 @@ static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
|
||||
fprintf(stderr, "Option is set to online/offline\n");
|
||||
ctdp_level.core_cpumask_size =
|
||||
alloc_cpu_set(&ctdp_level.core_cpumask);
|
||||
isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
|
||||
ret = isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
|
||||
if (ret) {
|
||||
isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
|
||||
return;
|
||||
}
|
||||
if (ctdp_level.cpu_count) {
|
||||
int i, max_cpus = get_topo_max_cpus();
|
||||
for (i = 0; i < max_cpus; ++i) {
|
||||
@ -2593,6 +2615,8 @@ static void usage(void)
|
||||
printf("\t[-i|--info] : Print platform information\n");
|
||||
printf("\t[-o|--out] : Output file\n");
|
||||
printf("\t\t\tDefault : stderr\n");
|
||||
printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n");
|
||||
printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n");
|
||||
printf("\t[-v|--version] : Print version\n");
|
||||
|
||||
printf("\nResult format\n");
|
||||
@ -2624,6 +2648,7 @@ static void print_version(void)
|
||||
static void cmdline(int argc, char **argv)
|
||||
{
|
||||
const char *pathname = "/dev/isst_interface";
|
||||
char *ptr;
|
||||
FILE *fp;
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
@ -2635,7 +2660,9 @@ static void cmdline(int argc, char **argv)
|
||||
{ "format", required_argument, 0, 'f' },
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "info", no_argument, 0, 'i' },
|
||||
{ "pause", required_argument, 0, 'p' },
|
||||
{ "out", required_argument, 0, 'o' },
|
||||
{ "retry", required_argument, 0, 'r' },
|
||||
{ "version", no_argument, 0, 'v' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
@ -2688,6 +2715,20 @@ static void cmdline(int argc, char **argv)
|
||||
fclose(outf);
|
||||
outf = fopen_or_exit(optarg, "w");
|
||||
break;
|
||||
case 'p':
|
||||
ret = strtol(optarg, &ptr, 10);
|
||||
if (!ret)
|
||||
fprintf(stderr, "Invalid pause interval, ignore\n");
|
||||
else
|
||||
mbox_delay = ret;
|
||||
break;
|
||||
case 'r':
|
||||
ret = strtol(optarg, &ptr, 10);
|
||||
if (!ret)
|
||||
fprintf(stderr, "Invalid retry count, ignore\n");
|
||||
else
|
||||
mbox_retries = ret;
|
||||
break;
|
||||
case 'v':
|
||||
print_version();
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user