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:
@@ -206,3 +206,20 @@ Description: This file exposes the firmware version of burnable voltage
|
|||||||
regulator devices.
|
regulator devices.
|
||||||
|
|
||||||
The file is read only.
|
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
|
- WAN enable and disable
|
||||||
- UWB enable and disable
|
- UWB enable and disable
|
||||||
- LCD Shadow (PrivacyGuard) enable and disable
|
- LCD Shadow (PrivacyGuard) enable and disable
|
||||||
|
- Lap mode sensor
|
||||||
|
|
||||||
A compatibility table by model and feature is maintained on the web
|
A compatibility table by model and feature is maintained on the web
|
||||||
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
|
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.
|
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
|
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:
|
review the laptop's user guide:
|
||||||
http://www.lenovo.com/shop/americas/content/user_guides/x1carbon_2_ug_en.pdf
|
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
|
Multiple Commands, Module Parameters
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
@@ -8610,6 +8610,12 @@ L: platform-driver-x86@vger.kernel.org
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/platform/x86/intel_atomisp2_pm.c
|
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
|
INTEL BROXTON PMC DRIVER
|
||||||
M: Mika Westerberg <mika.westerberg@linux.intel.com>
|
M: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||||
M: Zha Qipeng <qipeng.zha@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.
|
* Mellanox hotplug driver
|
||||||
* Copyright (c) 2016-2018 Vadim Pasternak <vadimp@mellanox.com>
|
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Copyright (C) 2016-2020 Mellanox Technologies
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
@@ -42,6 +16,7 @@
|
|||||||
#include <linux/platform_data/mlxreg.h>
|
#include <linux/platform_data/mlxreg.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/string_helpers.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
@@ -97,6 +72,23 @@ struct mlxreg_hotplug_priv_data {
|
|||||||
u8 not_asserted;
|
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,
|
static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
|
||||||
struct mlxreg_core_data *data)
|
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;
|
struct i2c_client *client;
|
||||||
|
|
||||||
/* Notify user by sending hwmon uevent. */
|
/* 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
|
* 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)
|
struct mlxreg_core_data *data)
|
||||||
{
|
{
|
||||||
/* Notify user by sending hwmon uevent. */
|
/* 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) {
|
if (data->hpdev.client) {
|
||||||
i2c_unregister_device(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_hotplug_platform_data *pdata;
|
||||||
struct mlxreg_core_item *item;
|
struct mlxreg_core_item *item;
|
||||||
struct mlxreg_core_data *data;
|
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);
|
pdata = dev_get_platdata(&priv->pdev->dev);
|
||||||
item = pdata->items;
|
item = pdata->items;
|
||||||
|
|
||||||
/* Go over all kinds of items - psu, pwr, fan. */
|
/* Go over all kinds of items - psu, pwr, fan. */
|
||||||
for (i = 0; i < pdata->counter; i++, item++) {
|
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;
|
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) = &PRIV_DEV_ATTR(id).dev_attr.attr;
|
||||||
PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
|
PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
|
||||||
GFP_KERNEL,
|
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 =
|
PRIV_DEV_ATTR(id).dev_attr.show =
|
||||||
mlxreg_hotplug_attr_show;
|
mlxreg_hotplug_attr_show;
|
||||||
PRIV_DEV_ATTR(id).nr = i;
|
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);
|
sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr);
|
||||||
|
data++;
|
||||||
|
id++;
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
|
num_attrs += k;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->group.attrs = devm_kcalloc(&priv->pdev->dev,
|
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;
|
item = pdata->items;
|
||||||
|
|
||||||
for (i = 0; i < pdata->counter; i++, item++) {
|
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. */
|
/* Clear group presense event. */
|
||||||
ret = regmap_write(priv->regmap, item->reg +
|
ret = regmap_write(priv->regmap, item->reg +
|
||||||
MLXREG_HOTPLUG_EVENT_OFF, 0);
|
MLXREG_HOTPLUG_EVENT_OFF, 0);
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
* @mlxreg_io_dev_attr: sysfs sensor device attribute array;
|
* @mlxreg_io_dev_attr: sysfs sensor device attribute array;
|
||||||
* @group: sysfs attribute group;
|
* @group: sysfs attribute group;
|
||||||
* @groups: list of sysfs attribute group for hwmon registration;
|
* @groups: list of sysfs attribute group for hwmon registration;
|
||||||
|
* @regsize: size of a register value;
|
||||||
*/
|
*/
|
||||||
struct mlxreg_io_priv_data {
|
struct mlxreg_io_priv_data {
|
||||||
struct platform_device *pdev;
|
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 sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM];
|
||||||
struct attribute_group group;
|
struct attribute_group group;
|
||||||
const struct attribute_group *groups[2];
|
const struct attribute_group *groups[2];
|
||||||
|
int regsize;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
|
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);
|
ret = regmap_read(regmap, data->reg, regval);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto access_error;
|
goto access_error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are three kinds of attributes: single bit, full register's
|
* There are four kinds of attributes: single bit, full register's
|
||||||
* bits and bit sequence. For the first kind field mask indicates which
|
* bits, bit sequence, bits in few registers For the first kind field
|
||||||
* bits are not related and field bit is set zero. For the second kind
|
* mask indicates which bits are not related and field bit is set zero.
|
||||||
* field mask is set to zero and field bit is set with all bits one.
|
* For the second kind field mask is set to zero and field bit is set
|
||||||
* No special handling for such kind of attributes - pass value as is.
|
* with all bits one. No special handling for such kind of attributes -
|
||||||
* For the third kind, field mask indicates which bits are related and
|
* pass value as is. For the third kind, the field mask indicates which
|
||||||
* field bit is set to the first bit number (from 1 to 32) is the bit
|
* bits are related and the field bit is set to the first bit number
|
||||||
* sequence.
|
* (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) {
|
if (!data->bit) {
|
||||||
/* Single 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. */
|
/* Clear relevant bits and set them to new value. */
|
||||||
*regval = (*regval & ~data->mask) | in_val;
|
*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:
|
access_error:
|
||||||
@@ -99,7 +116,8 @@ mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr,
|
|||||||
u32 regval = 0;
|
u32 regval = 0;
|
||||||
int ret;
|
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)
|
if (ret)
|
||||||
goto access_error;
|
goto access_error;
|
||||||
|
|
||||||
@@ -128,7 +146,7 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false,
|
ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false,
|
||||||
®val);
|
priv->regsize, ®val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto access_error;
|
goto access_error;
|
||||||
|
|
||||||
@@ -207,6 +225,9 @@ static int mlxreg_io_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->pdev = 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);
|
err = mlxreg_io_attr_init(priv);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@@ -140,7 +140,7 @@ config ACERHDF
|
|||||||
in the same node directory will tell you if it is "acerhdf".
|
in the same node directory will tell you if it is "acerhdf".
|
||||||
|
|
||||||
For more information about this driver see
|
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
|
If you have an Acer Aspire One netbook, say Y or M
|
||||||
here.
|
here.
|
||||||
@@ -748,6 +748,27 @@ config THINKPAD_ACPI_HOTKEY_POLL
|
|||||||
If you are not sure, say Y here. The driver enables polling only if
|
If you are not sure, say Y here. The driver enables polling only if
|
||||||
it is strictly necessary to do so.
|
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
|
config INTEL_ATOMISP2_PM
|
||||||
tristate "Intel AtomISP2 dummy / power-management driver"
|
tristate "Intel AtomISP2 dummy / power-management driver"
|
||||||
depends on PCI && IOSF_MBI && PM
|
depends on PCI && IOSF_MBI && PM
|
||||||
|
@@ -69,6 +69,7 @@ obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
|
|||||||
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
|
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
|
||||||
|
|
||||||
# Intel
|
# Intel
|
||||||
|
obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o
|
||||||
obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
|
obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
|
||||||
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
|
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
|
||||||
intel_cht_int33fe-objs := intel_cht_int33fe_common.o \
|
intel_cht_int33fe-objs := intel_cht_int33fe_common.o \
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* as soon as the upper/lower threshold is reached.
|
* as soon as the upper/lower threshold is reached.
|
||||||
*
|
*
|
||||||
* (C) 2009 - Peter Kaestle peter (a) piie.net
|
* (C) 2009 - Peter Kaestle peter (a) piie.net
|
||||||
* http://piie.net
|
* https://piie.net
|
||||||
* 2009 Borislav Petkov bp (a) alien8.de
|
* 2009 Borislav Petkov bp (a) alien8.de
|
||||||
*
|
*
|
||||||
* Inspired by and many thanks to:
|
* 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
|
* MBP5 2008/09 uses a `TI LP8543`_ backlight driver. All newer models
|
||||||
* use a `TI LP8545`_.
|
* use a `TI LP8545`_.
|
||||||
*
|
*
|
||||||
* .. _TI LP8543: http://www.ti.com/lit/ds/symlink/lp8543.pdf
|
* .. _TI LP8543: https://www.ti.com/lit/ds/symlink/lp8543.pdf
|
||||||
* .. _TI LP8545: http://www.ti.com/lit/ds/symlink/lp8545.pdf
|
* .. _TI LP8545: https://www.ti.com/lit/ds/symlink/lp8545.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int gmux_get_brightness(struct backlight_device *bd)
|
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
|
* switch the panel and the external DP connector and allocates a framebuffer
|
||||||
* for the selected GPU.
|
* for the selected GPU.
|
||||||
*
|
*
|
||||||
* .. _US 8,687,007 B2: http://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf
|
* .. _US 8,687,007 B2: https://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf
|
||||||
* .. _NXP CBTL06141: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
* .. _NXP CBTL06141: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
||||||
* .. _NXP CBTL06142: http://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
* .. _NXP CBTL06142: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
|
||||||
* .. _TI HD3SS212: http://www.ti.com/lit/ds/symlink/hd3ss212.pdf
|
* .. _TI HD3SS212: https://www.ti.com/lit/ds/symlink/hd3ss212.pdf
|
||||||
* .. _Pericom PI3VDP12412: https://www.pericom.com/assets/Datasheets/PI3VDP12412.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
|
* .. _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)
|
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,
|
.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)
|
static int dmi_matched(const struct dmi_system_id *dmi)
|
||||||
{
|
{
|
||||||
pr_info("Identified laptop model '%s'\n", dmi->ident);
|
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,
|
.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 */
|
/* Keyboard backlight change notification */
|
||||||
{ KE_IGNORE, 0x3f, { KEY_RESERVED } },
|
{ KE_IGNORE, 0x3f, { KEY_RESERVED } },
|
||||||
|
|
||||||
|
/* Backlight brightness level */
|
||||||
|
{ KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } },
|
||||||
|
{ KE_KEY, 0x58, { KEY_BRIGHTNESSUP } },
|
||||||
|
|
||||||
/* Mic mute */
|
/* Mic mute */
|
||||||
{ KE_KEY, 0x150, { KEY_MICMUTE } },
|
{ 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 } },
|
{ 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)
|
static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code)
|
||||||
{
|
{
|
||||||
struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
|
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]) {
|
switch (buffer_entry[1]) {
|
||||||
case 0x0000: /* One key pressed or event occurred */
|
case 0x0000: /* One key pressed or event occurred */
|
||||||
|
case 0x0012: /* Event with extended data occurred */
|
||||||
if (len > 2)
|
if (len > 2)
|
||||||
dell_wmi_process_key(wdev, 0x0000,
|
dell_wmi_process_key(wdev, buffer_entry[1],
|
||||||
buffer_entry[2]);
|
buffer_entry[2]);
|
||||||
/* Other entries could contain additional information */
|
/* Extended data is currently ignored */
|
||||||
break;
|
break;
|
||||||
case 0x0010: /* Sequence of keys pressed */
|
case 0x0010: /* Sequence of keys pressed */
|
||||||
case 0x0011: /* Sequence of events occurred */
|
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 <
|
u16 keycode = (bios_entry->keycode <
|
||||||
ARRAY_SIZE(bios_to_linux_keycode)) ?
|
ARRAY_SIZE(bios_to_linux_keycode)) ?
|
||||||
bios_to_linux_keycode[bios_entry->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
|
* 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_0000) +
|
||||||
ARRAY_SIZE(dell_wmi_keymap_type_0010) +
|
ARRAY_SIZE(dell_wmi_keymap_type_0010) +
|
||||||
ARRAY_SIZE(dell_wmi_keymap_type_0011) +
|
ARRAY_SIZE(dell_wmi_keymap_type_0011) +
|
||||||
|
ARRAY_SIZE(dell_wmi_keymap_type_0012) +
|
||||||
1,
|
1,
|
||||||
sizeof(struct key_entry), GFP_KERNEL);
|
sizeof(struct key_entry), GFP_KERNEL);
|
||||||
if (!keymap) {
|
if (!keymap) {
|
||||||
@@ -596,6 +611,13 @@ static int dell_wmi_input_setup(struct wmi_device *wdev)
|
|||||||
pos++;
|
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
|
* Now append also table with "legacy" events of type 0x0000. Some of
|
||||||
* them are reported also on laptops which have scancodes in DMI.
|
* 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;
|
return AE_OK;
|
||||||
|
|
||||||
if (acpi_match_device_ids(dev, ids) == 0)
|
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,
|
dev_info(&dev->dev,
|
||||||
"intel-hid: created platform device\n");
|
"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;
|
return AE_OK;
|
||||||
|
|
||||||
if (acpi_match_device_ids(dev, ids) == 0)
|
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,
|
dev_info(&dev->dev,
|
||||||
"intel-vbtn: created platform device\n");
|
"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)
|
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);
|
LIST_HEAD(resource_list);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
adev = ACPI_COMPANION(dev);
|
ret = acpi_dev_get_resources(adev, &resource_list,
|
||||||
if (!adev)
|
cht_int33fe_i2c_res_filter, &count);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
acpi_dev_get_resources(adev, &resource_list,
|
|
||||||
cht_int33fe_i2c_res_filter, &count);
|
|
||||||
|
|
||||||
acpi_dev_free_resource_list(&resource_list);
|
acpi_dev_free_resource_list(&resource_list);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@@ -415,7 +415,7 @@ static const struct pmc_bit_map tgl_lpm0_map[] = {
|
|||||||
{"PCIe_Gen3PLL_OFF_STS", BIT(20)},
|
{"PCIe_Gen3PLL_OFF_STS", BIT(20)},
|
||||||
{"OPIOPLL_OFF_STS", BIT(21)},
|
{"OPIOPLL_OFF_STS", BIT(21)},
|
||||||
{"OCPLL_OFF_STS", BIT(22)},
|
{"OCPLL_OFF_STS", BIT(22)},
|
||||||
{"AudioPLL_OFF_STS", BIT(23)},
|
{"MainPLL_OFF_STS", BIT(23)},
|
||||||
{"MIPIPLL_OFF_STS", BIT(24)},
|
{"MIPIPLL_OFF_STS", BIT(24)},
|
||||||
{"Fast_XTAL_Osc_OFF_STS", BIT(25)},
|
{"Fast_XTAL_Osc_OFF_STS", BIT(25)},
|
||||||
{"AC_Ring_Osc_OFF_STS", BIT(26)},
|
{"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);
|
msleep(10);
|
||||||
val_high = pmc_core_reg_read(pmcdev, SPT_PMC_MFPMC_OFFSET);
|
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",
|
seq_printf(s, "%-32s\tState: %s\n",
|
||||||
map[index].name,
|
map[index].name,
|
||||||
map[index].bit_mask & val_low ? "Not power gated" :
|
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_CPLD2_VER_OFFSET 0x01
|
||||||
#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02
|
#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02
|
||||||
#define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03
|
#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_RESET_CAUSE_OFFSET 0x1d
|
||||||
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e
|
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e
|
||||||
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f
|
#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_TMR_OFFSET 0xd1
|
||||||
#define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2
|
#define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2
|
||||||
#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3
|
#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_UFM_VERSION_OFFSET 0xe2
|
||||||
#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
|
#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
|
||||||
#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
|
#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),
|
.bit = GENMASK(7, 0),
|
||||||
.mode = 0444,
|
.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",
|
.label = "reset_long_pb",
|
||||||
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
.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),
|
.bit = GENMASK(7, 0),
|
||||||
.mode = 0444,
|
.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",
|
.label = "reset_long_pb",
|
||||||
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
.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),
|
.bit = GENMASK(7, 0),
|
||||||
.mode = 0444,
|
.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",
|
.label = "reset_long_pb",
|
||||||
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
.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),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(0),
|
.bit = BIT(0),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho2",
|
.label = "tacho2",
|
||||||
@@ -1735,6 +1849,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(1),
|
.bit = BIT(1),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho3",
|
.label = "tacho3",
|
||||||
@@ -1742,6 +1857,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(2),
|
.bit = BIT(2),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho4",
|
.label = "tacho4",
|
||||||
@@ -1749,6 +1865,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(3),
|
.bit = BIT(3),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho5",
|
.label = "tacho5",
|
||||||
@@ -1756,6 +1873,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(4),
|
.bit = BIT(4),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho6",
|
.label = "tacho6",
|
||||||
@@ -1763,6 +1881,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(5),
|
.bit = BIT(5),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho7",
|
.label = "tacho7",
|
||||||
@@ -1770,6 +1889,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(6),
|
.bit = BIT(6),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho8",
|
.label = "tacho8",
|
||||||
@@ -1777,6 +1897,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
|
||||||
.bit = BIT(7),
|
.bit = BIT(7),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho9",
|
.label = "tacho9",
|
||||||
@@ -1784,6 +1905,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||||
.bit = BIT(0),
|
.bit = BIT(0),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho10",
|
.label = "tacho10",
|
||||||
@@ -1791,6 +1913,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||||
.bit = BIT(1),
|
.bit = BIT(1),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho11",
|
.label = "tacho11",
|
||||||
@@ -1798,6 +1921,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||||
.bit = BIT(2),
|
.bit = BIT(2),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "tacho12",
|
.label = "tacho12",
|
||||||
@@ -1805,6 +1929,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
|||||||
.mask = GENMASK(7, 0),
|
.mask = GENMASK(7, 0),
|
||||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
|
||||||
.bit = BIT(3),
|
.bit = BIT(3),
|
||||||
|
.reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.label = "conf",
|
.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_CPLD2_VER_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_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_RESET_CAUSE_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_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_TMR_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_WD3_ACT_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_PWM1_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_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_CPLD2_VER_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_CPLD4_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_RESET_CAUSE_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_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_WD2_TLEFT_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_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_PWM1_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_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:1" },
|
||||||
{ .name = "apu:green:2" },
|
{ .name = "apu:green:2" },
|
||||||
{ .name = "apu:green:3" },
|
{ .name = "apu:green:3" },
|
||||||
{ .name = "apu:simswap" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct gpio_led_platform_data apu2_leds_pdata = {
|
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),
|
NULL, 1, GPIO_ACTIVE_LOW),
|
||||||
GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
|
GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
|
||||||
NULL, 2, GPIO_ACTIVE_LOW),
|
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
|
// 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;
|
struct system76_data *data;
|
||||||
|
|
||||||
data = container_of(led, struct system76_data, ap_led);
|
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
|
// 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
|
// 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;
|
struct system76_data *data;
|
||||||
|
|
||||||
data = container_of(led, struct system76_data, kb_led);
|
data = container_of(led, struct system76_data, kb_led);
|
||||||
data->kb_brightness = value;
|
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
|
// 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.name = "system76_acpi::airplane";
|
||||||
data->ap_led.flags = LED_CORE_SUSPENDRESUME;
|
data->ap_led.flags = LED_CORE_SUSPENDRESUME;
|
||||||
data->ap_led.brightness_get = ap_led_get;
|
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.max_brightness = 1;
|
||||||
data->ap_led.default_trigger = "rfkill-none";
|
data->ap_led.default_trigger = "rfkill-none";
|
||||||
err = devm_led_classdev_register(&acpi_dev->dev, &data->ap_led);
|
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.name = "system76_acpi::kbd_backlight";
|
||||||
data->kb_led.flags = LED_BRIGHT_HW_CHANGED | LED_CORE_SUSPENDRESUME;
|
data->kb_led.flags = LED_BRIGHT_HW_CHANGED | LED_CORE_SUSPENDRESUME;
|
||||||
data->kb_led.brightness_get = kb_led_get;
|
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")) {
|
if (acpi_has_method(acpi_device_handle(data->acpi_dev), "SKBC")) {
|
||||||
data->kb_led.max_brightness = 255;
|
data->kb_led.max_brightness = 255;
|
||||||
data->kb_toggle_brightness = 72;
|
data->kb_toggle_brightness = 72;
|
||||||
|
@@ -4030,8 +4030,8 @@ static bool hotkey_notify_6xxx(const u32 hkey,
|
|||||||
return true;
|
return true;
|
||||||
case TP_HKEY_EV_THM_CSM_COMPLETED:
|
case TP_HKEY_EV_THM_CSM_COMPLETED:
|
||||||
pr_debug("EC reports: Thermal Control Command set completed (DYTC)\n");
|
pr_debug("EC reports: Thermal Control Command set completed (DYTC)\n");
|
||||||
/* recommended action: do nothing, we don't have
|
/* Thermal event - pass on to event handler */
|
||||||
* Lenovo ATM information */
|
tpacpi_driver_event(hkey);
|
||||||
return true;
|
return true;
|
||||||
case TP_HKEY_EV_THM_TRANSFM_CHANGED:
|
case TP_HKEY_EV_THM_TRANSFM_CHANGED:
|
||||||
pr_debug("EC reports: Thermal Transformation changed (GMTS)\n");
|
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");
|
pr_warn("Cannot enable backlight brightness support, ACPI is already handling it. Refer to the acpi_backlight kernel parameter.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (tp_features.bright_acpimode && brightness_enable > 1) {
|
} else if (!tp_features.bright_acpimode) {
|
||||||
pr_notice("Standard ACPI backlight interface not available, thinkpad_acpi native brightness control enabled\n");
|
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
|
* Check for module parameter bogosity, note that we
|
||||||
* init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be
|
* 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).
|
* does so, its initial value is meaningless (0x07).
|
||||||
*
|
*
|
||||||
* For firmware bugs, refer to:
|
* 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.
|
* mode.
|
||||||
*
|
*
|
||||||
* For firmware bugs, refer to:
|
* 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 GET_STOP "BCSG"
|
||||||
#define SET_STOP "BCSS"
|
#define SET_STOP "BCSS"
|
||||||
|
|
||||||
#define START_ATTR "charge_start_threshold"
|
|
||||||
#define STOP_ATTR "charge_stop_threshold"
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BAT_ANY = 0,
|
BAT_ANY = 0,
|
||||||
BAT_PRIMARY = 1,
|
BAT_PRIMARY = 1,
|
||||||
@@ -9603,38 +9603,52 @@ static ssize_t tpacpi_battery_show(int what,
|
|||||||
return sprintf(buf, "%d\n", ret);
|
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,
|
struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
return tpacpi_battery_show(THRESHOLD_START, device, 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,
|
struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
return tpacpi_battery_show(THRESHOLD_STOP, device, 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,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
return tpacpi_battery_store(THRESHOLD_START, dev, buf, 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,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
return tpacpi_battery_store(THRESHOLD_STOP, dev, buf, count);
|
return tpacpi_battery_store(THRESHOLD_STOP, dev, buf, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_RW(charge_start_threshold);
|
static DEVICE_ATTR_RW(charge_control_start_threshold);
|
||||||
static DEVICE_ATTR_RW(charge_stop_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[] = {
|
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_start_threshold.attr,
|
||||||
&dev_attr_charge_stop_threshold.attr,
|
&dev_attr_charge_stop_threshold.attr,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -9803,6 +9817,105 @@ static struct ibm_struct lcdshadow_driver_data = {
|
|||||||
.write = lcdshadow_write,
|
.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);
|
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)
|
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
|
* X32 or newer, all Z series; Some models must have an
|
||||||
* up-to-date BIOS or they will not be detected.
|
* 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))) {
|
while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
|
||||||
if (sscanf(dev->name,
|
if (sscanf(dev->name,
|
||||||
@@ -10288,6 +10405,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
|
|||||||
.init = tpacpi_lcdshadow_init,
|
.init = tpacpi_lcdshadow_init,
|
||||||
.data = &lcdshadow_driver_data,
|
.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)
|
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
|
* DMI matching for module autoloading
|
||||||
*
|
*
|
||||||
* See http://thinkwiki.org/wiki/List_of_DMI_IDs
|
* See https://thinkwiki.org/wiki/List_of_DMI_IDs
|
||||||
* See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
|
* See https://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
|
||||||
*
|
*
|
||||||
* Only models listed in thinkwiki will be supported, so add yours
|
* Only models listed in thinkwiki will be supported, so add yours
|
||||||
* if it is not there yet.
|
* if it is not there yet.
|
||||||
|
@@ -75,11 +75,13 @@ struct mlxreg_hotplug_device {
|
|||||||
* @mask: attribute access mask;
|
* @mask: attribute access mask;
|
||||||
* @bit: attribute effective bit;
|
* @bit: attribute effective bit;
|
||||||
* @capability: attribute capability register;
|
* @capability: attribute capability register;
|
||||||
|
* @reg_prsnt: attribute presence register;
|
||||||
* @mode: access mode;
|
* @mode: access mode;
|
||||||
* @np - pointer to node platform associated with attribute;
|
* @np - pointer to node platform associated with attribute;
|
||||||
* @hpdev - hotplug device data;
|
* @hpdev - hotplug device data;
|
||||||
* @health_cntr: dynamic device health indication counter;
|
* @health_cntr: dynamic device health indication counter;
|
||||||
* @attached: true if device has been attached after good health indication;
|
* @attached: true if device has been attached after good health indication;
|
||||||
|
* @regnum: number of registers occupied by multi-register attribute;
|
||||||
*/
|
*/
|
||||||
struct mlxreg_core_data {
|
struct mlxreg_core_data {
|
||||||
char label[MLXREG_CORE_LABEL_MAX_SIZE];
|
char label[MLXREG_CORE_LABEL_MAX_SIZE];
|
||||||
@@ -87,11 +89,13 @@ struct mlxreg_core_data {
|
|||||||
u32 mask;
|
u32 mask;
|
||||||
u32 bit;
|
u32 bit;
|
||||||
u32 capability;
|
u32 capability;
|
||||||
|
u32 reg_prsnt;
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
struct mlxreg_hotplug_device hpdev;
|
struct mlxreg_hotplug_device hpdev;
|
||||||
u8 health_cntr;
|
u8 health_cntr;
|
||||||
bool attached;
|
bool attached;
|
||||||
|
u8 regnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#ifndef _LINUX_STRING_HELPERS_H_
|
#ifndef _LINUX_STRING_HELPERS_H_
|
||||||
#define _LINUX_STRING_HELPERS_H_
|
#define _LINUX_STRING_HELPERS_H_
|
||||||
|
|
||||||
|
#include <linux/ctype.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct file;
|
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);
|
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(const char *src, gfp_t gfp);
|
||||||
char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp);
|
char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp);
|
||||||
char *kstrdup_quotable_file(struct file *file, 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.
|
* @logical_cpu: Logical CPU number to get target PCI device.
|
||||||
* @reg: PUNIT register offset
|
* @reg: PUNIT register offset
|
||||||
* @value: For write operation value to write and for
|
* @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.
|
* Structure to specify read/write data to PUNIT registers.
|
||||||
*/
|
*/
|
||||||
|
@@ -238,6 +238,28 @@ static const struct test_string_2 escape1[] __initconst = {{
|
|||||||
/* terminator */
|
/* 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,
|
static __init const char *test_string_find_match(const struct test_string_2 *s2,
|
||||||
unsigned int flags)
|
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");
|
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)
|
static int __init test_string_helpers_init(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
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_get_size();
|
test_string_get_size();
|
||||||
|
|
||||||
|
/* Test string upper(), string_lower() */
|
||||||
|
test_string_upper_lower();
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
module_init(test_string_helpers_init);
|
module_init(test_string_helpers_init);
|
||||||
|
@@ -15,7 +15,7 @@ struct process_cmd_struct {
|
|||||||
int arg;
|
int arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *version_str = "v1.4";
|
static const char *version_str = "v1.5";
|
||||||
static const int supported_api_ver = 1;
|
static const int supported_api_ver = 1;
|
||||||
static struct isst_if_platform_info isst_platform_info;
|
static struct isst_if_platform_info isst_platform_info;
|
||||||
static char *progname;
|
static char *progname;
|
||||||
@@ -44,6 +44,9 @@ static int force_online_offline;
|
|||||||
static int auto_mode;
|
static int auto_mode;
|
||||||
static int fact_enable_fail;
|
static int fact_enable_fail;
|
||||||
|
|
||||||
|
static int mbox_delay;
|
||||||
|
static int mbox_retries = 3;
|
||||||
|
|
||||||
/* clos related */
|
/* clos related */
|
||||||
static int current_clos = -1;
|
static int current_clos = -1;
|
||||||
static int clos_epp = -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)
|
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;
|
struct cpu_topology cpu_top;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -230,7 +233,7 @@ err_ret:
|
|||||||
|
|
||||||
static void store_cpu_topology(void)
|
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;
|
FILE *fp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -247,6 +250,8 @@ static void store_cpu_topology(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Caching topology information\n");
|
||||||
|
|
||||||
for (i = 0; i < topo_max_cpus; ++i) {
|
for (i = 0; i < topo_max_cpus; ++i) {
|
||||||
struct cpu_topology cpu_top;
|
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)
|
unsigned int req_data, unsigned int *resp)
|
||||||
{
|
{
|
||||||
const char *pathname = "/dev/isst_interface";
|
const char *pathname = "/dev/isst_interface";
|
||||||
int fd;
|
int fd, retry;
|
||||||
struct isst_if_mbox_cmds mbox_cmds = { 0 };
|
struct isst_if_mbox_cmds mbox_cmds = { 0 };
|
||||||
|
|
||||||
debug_printf(
|
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].parameter = parameter;
|
||||||
mbox_cmds.mbox_cmd[0].req_data = req_data;
|
mbox_cmds.mbox_cmd[0].req_data = req_data;
|
||||||
|
|
||||||
|
if (mbox_delay)
|
||||||
|
usleep(mbox_delay * 1000);
|
||||||
|
|
||||||
fd = open(pathname, O_RDWR);
|
fd = open(pathname, O_RDWR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
err(-1, "%s open failed", pathname);
|
err(-1, "%s open failed", pathname);
|
||||||
|
|
||||||
if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
|
retry = mbox_retries;
|
||||||
if (errno == ENOTTY) {
|
|
||||||
perror("ISST_IF_MBOX_COMMAND\n");
|
do {
|
||||||
fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
|
if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
|
||||||
exit(0);
|
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(
|
} while (retry);
|
||||||
"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);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
if (!retry) {
|
||||||
|
debug_printf("Failed mbox command even after retries\n");
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
return 0;
|
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");
|
fprintf(stderr, "Option is set to online/offline\n");
|
||||||
ctdp_level.core_cpumask_size =
|
ctdp_level.core_cpumask_size =
|
||||||
alloc_cpu_set(&ctdp_level.core_cpumask);
|
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) {
|
if (ctdp_level.cpu_count) {
|
||||||
int i, max_cpus = get_topo_max_cpus();
|
int i, max_cpus = get_topo_max_cpus();
|
||||||
for (i = 0; i < max_cpus; ++i) {
|
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[-i|--info] : Print platform information\n");
|
||||||
printf("\t[-o|--out] : Output file\n");
|
printf("\t[-o|--out] : Output file\n");
|
||||||
printf("\t\t\tDefault : stderr\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("\t[-v|--version] : Print version\n");
|
||||||
|
|
||||||
printf("\nResult format\n");
|
printf("\nResult format\n");
|
||||||
@@ -2624,6 +2648,7 @@ static void print_version(void)
|
|||||||
static void cmdline(int argc, char **argv)
|
static void cmdline(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *pathname = "/dev/isst_interface";
|
const char *pathname = "/dev/isst_interface";
|
||||||
|
char *ptr;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int opt;
|
int opt;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
@@ -2635,7 +2660,9 @@ static void cmdline(int argc, char **argv)
|
|||||||
{ "format", required_argument, 0, 'f' },
|
{ "format", required_argument, 0, 'f' },
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
{ "info", no_argument, 0, 'i' },
|
{ "info", no_argument, 0, 'i' },
|
||||||
|
{ "pause", required_argument, 0, 'p' },
|
||||||
{ "out", required_argument, 0, 'o' },
|
{ "out", required_argument, 0, 'o' },
|
||||||
|
{ "retry", required_argument, 0, 'r' },
|
||||||
{ "version", no_argument, 0, 'v' },
|
{ "version", no_argument, 0, 'v' },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
@@ -2688,6 +2715,20 @@ static void cmdline(int argc, char **argv)
|
|||||||
fclose(outf);
|
fclose(outf);
|
||||||
outf = fopen_or_exit(optarg, "w");
|
outf = fopen_or_exit(optarg, "w");
|
||||||
break;
|
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':
|
case 'v':
|
||||||
print_version();
|
print_version();
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user