Update patches for power-button wakeup issues on Bay / Cherry Trail devices
Add patches to fix an IRQ storm on devices with a MAX17042 fuel-gauge
This commit is contained in:
parent
717a8b5a3c
commit
51a2ae761f
163
0001-Input-gpio_keys-Allow-suppression-of-input-events-fo.patch
Normal file
163
0001-Input-gpio_keys-Allow-suppression-of-input-events-fo.patch
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
From 25bb14c1e78e641049fd1ee0c404a9ccd2755e44 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
Date: Sat, 22 Jul 2017 13:00:05 +0200
|
||||||
|
Subject: [PATCH 1/2] Input: gpio_keys - Allow suppression of input events for
|
||||||
|
wakeup button presses
|
||||||
|
|
||||||
|
In some cases it is undesirable for a wakeup button to send input events
|
||||||
|
to userspace if pressed to wakeup the system (if pressed during suspend).
|
||||||
|
|
||||||
|
A typical example of this is the power-button on laptops / tablets,
|
||||||
|
sending a KEY_POWER event to userspace when woken up with the power-button
|
||||||
|
will cause userspace to immediately suspend the system again which is
|
||||||
|
undesirable.
|
||||||
|
|
||||||
|
For power-buttons attached to a PMIC, or handled by e.g. ACPI, not sending
|
||||||
|
an input event in this case is take care of by the PMIC / ACPI hardware /
|
||||||
|
code. But in the case of a GPIO button we need to explicitly suppress the
|
||||||
|
sending of the input event.
|
||||||
|
|
||||||
|
This commit adds support for this by adding a no_wakeup_events bool to
|
||||||
|
struct gpio_keys_button, which platform code can set to suppress the
|
||||||
|
input events for presses of wakeup keys during suspend.
|
||||||
|
|
||||||
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
---
|
||||||
|
Changes in v2:
|
||||||
|
-This is a rewrite if my "Input: gpio_keys - Do not report wake button
|
||||||
|
presses as evdev events" patch.
|
||||||
|
-Instead of unconditionally ignoring presses of all wake-up buttons during
|
||||||
|
suspend, this rewrite makes this configurable per button
|
||||||
|
-This version uses a timer to delay clearing the suspended flag for software
|
||||||
|
debouncing, rather then jiffy compare magic
|
||||||
|
---
|
||||||
|
drivers/input/keyboard/gpio_keys.c | 33 +++++++++++++++++++++++++++++++--
|
||||||
|
include/linux/gpio_keys.h | 3 +++
|
||||||
|
2 files changed, 34 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
|
||||||
|
index a047b9af8369..fa3a58620407 100644
|
||||||
|
--- a/drivers/input/keyboard/gpio_keys.c
|
||||||
|
+++ b/drivers/input/keyboard/gpio_keys.c
|
||||||
|
@@ -38,6 +38,7 @@ struct gpio_button_data {
|
||||||
|
|
||||||
|
unsigned short *code;
|
||||||
|
|
||||||
|
+ struct timer_list unsuspend_timer;
|
||||||
|
struct timer_list release_timer;
|
||||||
|
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
|
||||||
|
|
||||||
|
@@ -371,6 +372,9 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (state && bdata->button->no_wakeup_events && bdata->suspended)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
if (type == EV_ABS) {
|
||||||
|
if (state)
|
||||||
|
input_event(input, type, button->code, button->value);
|
||||||
|
@@ -400,6 +404,9 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
|
||||||
|
if (bdata->button->wakeup) {
|
||||||
|
const struct gpio_keys_button *button = bdata->button;
|
||||||
|
|
||||||
|
+ if (bdata->button->no_wakeup_events && bdata->suspended)
|
||||||
|
+ return IRQ_HANDLED;
|
||||||
|
+
|
||||||
|
pm_stay_awake(bdata->input->dev.parent);
|
||||||
|
if (bdata->suspended &&
|
||||||
|
(button->type == 0 || button->type == EV_KEY)) {
|
||||||
|
@@ -445,9 +452,13 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
|
||||||
|
spin_lock_irqsave(&bdata->lock, flags);
|
||||||
|
|
||||||
|
if (!bdata->key_pressed) {
|
||||||
|
- if (bdata->button->wakeup)
|
||||||
|
+ if (bdata->button->wakeup) {
|
||||||
|
pm_wakeup_event(bdata->input->dev.parent, 0);
|
||||||
|
|
||||||
|
+ if (bdata->button->no_wakeup_events && bdata->suspended)
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
input_event(input, EV_KEY, *bdata->code, 1);
|
||||||
|
input_sync(input);
|
||||||
|
|
||||||
|
@@ -468,6 +479,13 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void gpio_keys_unsuspend_timer(unsigned long _data)
|
||||||
|
+{
|
||||||
|
+ struct gpio_button_data *bdata = (struct gpio_button_data *)_data;
|
||||||
|
+
|
||||||
|
+ bdata->suspended = false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void gpio_keys_quiesce_key(void *data)
|
||||||
|
{
|
||||||
|
struct gpio_button_data *bdata = data;
|
||||||
|
@@ -476,6 +494,8 @@ static void gpio_keys_quiesce_key(void *data)
|
||||||
|
cancel_delayed_work_sync(&bdata->work);
|
||||||
|
else
|
||||||
|
del_timer_sync(&bdata->release_timer);
|
||||||
|
+
|
||||||
|
+ del_timer_sync(&bdata->unsuspend_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gpio_keys_setup_key(struct platform_device *pdev,
|
||||||
|
@@ -496,6 +516,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
|
||||||
|
bdata->input = input;
|
||||||
|
bdata->button = button;
|
||||||
|
spin_lock_init(&bdata->lock);
|
||||||
|
+ setup_timer(&bdata->unsuspend_timer, gpio_keys_unsuspend_timer,
|
||||||
|
+ (unsigned long)bdata);
|
||||||
|
|
||||||
|
if (child) {
|
||||||
|
bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL,
|
||||||
|
@@ -868,6 +890,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
|
||||||
|
struct gpio_button_data *bdata = &ddata->data[i];
|
||||||
|
if (bdata->button->wakeup)
|
||||||
|
enable_irq_wake(bdata->irq);
|
||||||
|
+ del_timer_sync(&bdata->unsuspend_timer);
|
||||||
|
bdata->suspended = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@@ -892,7 +915,13 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
|
||||||
|
struct gpio_button_data *bdata = &ddata->data[i];
|
||||||
|
if (bdata->button->wakeup)
|
||||||
|
disable_irq_wake(bdata->irq);
|
||||||
|
- bdata->suspended = false;
|
||||||
|
+ if (bdata->button->no_wakeup_events) {
|
||||||
|
+ mod_timer(&bdata->unsuspend_timer, jiffies +
|
||||||
|
+ msecs_to_jiffies(
|
||||||
|
+ bdata->software_debounce));
|
||||||
|
+ } else {
|
||||||
|
+ bdata->suspended = false;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mutex_lock(&input->mutex);
|
||||||
|
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
|
||||||
|
index 0b71024c082c..d8a85e52b6bb 100644
|
||||||
|
--- a/include/linux/gpio_keys.h
|
||||||
|
+++ b/include/linux/gpio_keys.h
|
||||||
|
@@ -15,6 +15,8 @@ struct device;
|
||||||
|
* @debounce_interval: debounce ticks interval in msecs
|
||||||
|
* @can_disable: %true indicates that userspace is allowed to
|
||||||
|
* disable button via sysfs
|
||||||
|
+ * @no_wakeup_events: For wake-up source buttons only, if %true then no input
|
||||||
|
+ * events will be generated if pressed while suspended
|
||||||
|
* @value: axis value for %EV_ABS
|
||||||
|
* @irq: Irq number in case of interrupt keys
|
||||||
|
*/
|
||||||
|
@@ -27,6 +29,7 @@ struct gpio_keys_button {
|
||||||
|
int wakeup;
|
||||||
|
int debounce_interval;
|
||||||
|
bool can_disable;
|
||||||
|
+ bool no_wakeup_events;
|
||||||
|
int value;
|
||||||
|
unsigned int irq;
|
||||||
|
};
|
||||||
|
--
|
||||||
|
2.13.4
|
||||||
|
|
@ -0,0 +1,78 @@
|
|||||||
|
From 075bb90dbb4d894938c5859e3850987238db9cd8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
Date: Fri, 11 Aug 2017 22:30:55 +0200
|
||||||
|
Subject: [PATCH 1/2] power: supply: max17042_battery: Add support for ACPI
|
||||||
|
enumeration
|
||||||
|
|
||||||
|
Some x86 devices enumerate a max17047 fuel-gauge through a MAX17047
|
||||||
|
ACPI firmware-node, add support for this.
|
||||||
|
|
||||||
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/power/supply/max17042_battery.c | 22 +++++++++++++++++++++-
|
||||||
|
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
|
||||||
|
index aecaaa2b0586..b2ddb7eb69c6 100644
|
||||||
|
--- a/drivers/power/supply/max17042_battery.c
|
||||||
|
+++ b/drivers/power/supply/max17042_battery.c
|
||||||
|
@@ -22,6 +22,7 @@
|
||||||
|
* This driver is based on max17040_battery.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <linux/acpi.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
@@ -982,6 +983,8 @@ static int max17042_probe(struct i2c_client *client,
|
||||||
|
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||||
|
const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
|
||||||
|
struct power_supply_config psy_cfg = {};
|
||||||
|
+ const struct acpi_device_id *acpi_id;
|
||||||
|
+ struct device *dev = &client->dev;
|
||||||
|
struct max17042_chip *chip;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
@@ -995,7 +998,15 @@ static int max17042_probe(struct i2c_client *client,
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
chip->client = client;
|
||||||
|
- chip->chip_type = id->driver_data;
|
||||||
|
+ if (id) {
|
||||||
|
+ chip->chip_type = id->driver_data;
|
||||||
|
+ } else {
|
||||||
|
+ acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
|
||||||
|
+ if (!acpi_id)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
+ chip->chip_type = acpi_id->driver_data;
|
||||||
|
+ }
|
||||||
|
chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config);
|
||||||
|
if (IS_ERR(chip->regmap)) {
|
||||||
|
dev_err(&client->dev, "Failed to initialize regmap\n");
|
||||||
|
@@ -1104,6 +1115,14 @@ static int max17042_resume(struct device *dev)
|
||||||
|
static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
|
||||||
|
max17042_resume);
|
||||||
|
|
||||||
|
+#ifdef CONFIG_ACPI
|
||||||
|
+static const struct acpi_device_id max17042_acpi_match[] = {
|
||||||
|
+ { "MAX17047", MAXIM_DEVICE_TYPE_MAX17047 },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(acpi, max17042_acpi_match);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id max17042_dt_match[] = {
|
||||||
|
{ .compatible = "maxim,max17042" },
|
||||||
|
@@ -1125,6 +1144,7 @@ MODULE_DEVICE_TABLE(i2c, max17042_id);
|
||||||
|
static struct i2c_driver max17042_i2c_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "max17042",
|
||||||
|
+ .acpi_match_table = ACPI_PTR(max17042_acpi_match),
|
||||||
|
.of_match_table = of_match_ptr(max17042_dt_match),
|
||||||
|
.pm = &max17042_pm_ops,
|
||||||
|
},
|
||||||
|
--
|
||||||
|
2.13.4
|
||||||
|
|
@ -0,0 +1,62 @@
|
|||||||
|
From d561f0543506bc12e7b3355efddb0bfd7ca83c74 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
Date: Sat, 22 Jul 2017 13:17:36 +0200
|
||||||
|
Subject: [PATCH 2/2] Input: soc_button_array - Suppress power button presses
|
||||||
|
during suspend
|
||||||
|
|
||||||
|
If the power-button is pressed to wakeup the laptop/tablet from suspend
|
||||||
|
and we report a KEY_POWER event to userspace when woken up this will cause
|
||||||
|
userspace to immediately suspend the system again which is undesirable.
|
||||||
|
|
||||||
|
This commit sets the new no_wakeup_events flag in the gpio_keys_button
|
||||||
|
struct for the power-button suppressing the undesirable KEY_POWER input
|
||||||
|
events on wake-up.
|
||||||
|
|
||||||
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
---
|
||||||
|
Changes in v2:
|
||||||
|
-New patch in v2 of this patch-set
|
||||||
|
---
|
||||||
|
drivers/input/misc/soc_button_array.c | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
|
||||||
|
index f600f3a7a3c6..27b99831cb97 100644
|
||||||
|
--- a/drivers/input/misc/soc_button_array.c
|
||||||
|
+++ b/drivers/input/misc/soc_button_array.c
|
||||||
|
@@ -27,6 +27,7 @@ struct soc_button_info {
|
||||||
|
unsigned int event_code;
|
||||||
|
bool autorepeat;
|
||||||
|
bool wakeup;
|
||||||
|
+ bool no_wakeup_events;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -100,6 +101,7 @@ soc_button_device_create(struct platform_device *pdev,
|
||||||
|
gpio_keys[n_buttons].active_low = 1;
|
||||||
|
gpio_keys[n_buttons].desc = info->name;
|
||||||
|
gpio_keys[n_buttons].wakeup = info->wakeup;
|
||||||
|
+ gpio_keys[n_buttons].no_wakeup_events = info->no_wakeup_events;
|
||||||
|
/* These devices often use cheap buttons, use 50 ms debounce */
|
||||||
|
gpio_keys[n_buttons].debounce_interval = 50;
|
||||||
|
n_buttons++;
|
||||||
|
@@ -185,6 +187,7 @@ static int soc_button_parse_btn_desc(struct device *dev,
|
||||||
|
info->name = "power";
|
||||||
|
info->event_code = KEY_POWER;
|
||||||
|
info->wakeup = true;
|
||||||
|
+ info->no_wakeup_events = true;
|
||||||
|
} else if (upage == 0x07 && usage == 0xe3) {
|
||||||
|
info->name = "home";
|
||||||
|
info->event_code = KEY_LEFTMETA;
|
||||||
|
@@ -369,7 +372,7 @@ static int soc_button_probe(struct platform_device *pdev)
|
||||||
|
* Platforms"
|
||||||
|
*/
|
||||||
|
static struct soc_button_info soc_button_PNP0C40[] = {
|
||||||
|
- { "power", 0, EV_KEY, KEY_POWER, false, true },
|
||||||
|
+ { "power", 0, EV_KEY, KEY_POWER, false, true, true },
|
||||||
|
{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
|
||||||
|
{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
|
||||||
|
{ "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false },
|
||||||
|
--
|
||||||
|
2.13.4
|
||||||
|
|
@ -0,0 +1,80 @@
|
|||||||
|
From 27b9d46d25c873b351757c44ce523bf0ede1d08e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
Date: Mon, 14 Aug 2017 11:02:59 +0200
|
||||||
|
Subject: [PATCH 2/2] power: supply: max17042_battery: Fix ACPI interrupt
|
||||||
|
issues
|
||||||
|
|
||||||
|
On some x86/ACPI boards the DSDT defines an ACPI event handler for
|
||||||
|
the max17047 IRQ, this causes several problems:
|
||||||
|
|
||||||
|
1) We need to share the IRQ to avoid an error getting it
|
||||||
|
|
||||||
|
2) Even of we are willing to share, we may fail to share because some
|
||||||
|
DSDTs claim it exclusivly
|
||||||
|
|
||||||
|
3) If we are unable to share the IRQ, or the IRQ is only listed as an
|
||||||
|
ACPI event source and not in the max1704 firmware node, then the
|
||||||
|
charge threshold IRQ (which is used to give an IRQ every 1 percent
|
||||||
|
charge change) becomes a problem, the ACPI event handler will not
|
||||||
|
update this to the next 1 percent threshold, so the IRQ keeps firing
|
||||||
|
and we get an IRQ storm pegging 1 CPU core.
|
||||||
|
|
||||||
|
This happens despite the max17042 driver not setting the charge
|
||||||
|
threshold because Windows uses it and leaves it set on reboot.
|
||||||
|
|
||||||
|
So if we are unable to get the IRQ we need to reprogram the
|
||||||
|
charge threshold to its disabled setting.
|
||||||
|
|
||||||
|
This commit fixes al of the above, while at it it also makes the error
|
||||||
|
msg when being unable to get the IRQ consistent with other messages.
|
||||||
|
|
||||||
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||||
|
---
|
||||||
|
drivers/power/supply/max17042_battery.c | 20 +++++++++++++++-----
|
||||||
|
1 file changed, 15 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
|
||||||
|
index b2ddb7eb69c6..18a44e4ed6ff 100644
|
||||||
|
--- a/drivers/power/supply/max17042_battery.c
|
||||||
|
+++ b/drivers/power/supply/max17042_battery.c
|
||||||
|
@@ -1050,11 +1050,18 @@ static int max17042_probe(struct i2c_client *client,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->irq) {
|
||||||
|
+ unsigned int flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * On ACPI systems the IRQ may be handled by ACPI-event code,
|
||||||
|
+ * so we need to share (if the ACPI code is willing to share).
|
||||||
|
+ */
|
||||||
|
+ if (acpi_id)
|
||||||
|
+ flags |= IRQF_SHARED | IRQF_PROBE_SHARED;
|
||||||
|
+
|
||||||
|
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||||
|
NULL,
|
||||||
|
- max17042_thread_handler,
|
||||||
|
- IRQF_TRIGGER_FALLING |
|
||||||
|
- IRQF_ONESHOT,
|
||||||
|
+ max17042_thread_handler, flags,
|
||||||
|
chip->battery->desc->name,
|
||||||
|
chip);
|
||||||
|
if (!ret) {
|
||||||
|
@@ -1064,10 +1071,13 @@ static int max17042_probe(struct i2c_client *client,
|
||||||
|
max17042_set_soc_threshold(chip, 1);
|
||||||
|
} else {
|
||||||
|
client->irq = 0;
|
||||||
|
- dev_err(&client->dev, "%s(): cannot get IRQ\n",
|
||||||
|
- __func__);
|
||||||
|
+ if (ret != -EBUSY)
|
||||||
|
+ dev_err(&client->dev, "Failed to get IRQ\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ /* Not able to update the charge threshold when exceeded? -> disable */
|
||||||
|
+ if (!client->irq)
|
||||||
|
+ regmap_write(chip->regmap, MAX17042_SALRT_Th, 0xff00);
|
||||||
|
|
||||||
|
regmap_read(chip->regmap, MAX17042_STATUS, &val);
|
||||||
|
if (val & STATUS_POR_BIT) {
|
||||||
|
--
|
||||||
|
2.13.4
|
||||||
|
|
@ -1,150 +0,0 @@
|
|||||||
From 02b823a4d28ffb5fde5192799abd934d9de95630 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Hans de Goede <hdegoede@redhat.com>
|
|
||||||
Date: Fri, 6 Jan 2017 20:08:11 +0100
|
|
||||||
Subject: [PATCH 12/16] Input: gpio_keys - Do not report wake button presses as
|
|
||||||
evdev events
|
|
||||||
|
|
||||||
If a button is a wake button, it may still be bouncing from the press
|
|
||||||
to wakeup the device by the time the gpio interrupts get enabled again
|
|
||||||
and / or the gpio_keys_report_state call from gpio_keys_resume may
|
|
||||||
find the button still pressed and report this as a new press.
|
|
||||||
|
|
||||||
This is undesirable, esp. since the powerbutton on tablets is typically
|
|
||||||
a wakeup source and uses the gpio_keys driver on some tablets, leading
|
|
||||||
to userspace immediately re-suspending the tablet after the powerbutton
|
|
||||||
is pressed, due to it seeing a powerbutton press.
|
|
||||||
|
|
||||||
This commit ignores wakeup button presses for the first 1 second after
|
|
||||||
resume (and while resumed, as the workqueue may run before the resume
|
|
||||||
function runs), avoiding this problem.
|
|
||||||
|
|
||||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
||||||
---
|
|
||||||
Note: maybe we should make WAKE_DEBOUNCE part of gpio_keys_button and
|
|
||||||
only do this when drivers / platform-data set this to a non-zero value ?
|
|
||||||
---
|
|
||||||
drivers/input/keyboard/gpio_keys.c | 49 ++++++++++++++++++++++++++++++++++++--
|
|
||||||
1 file changed, 47 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
|
|
||||||
index da3d362f21b1..e1488b534e7d 100644
|
|
||||||
--- a/drivers/input/keyboard/gpio_keys.c
|
|
||||||
+++ b/drivers/input/keyboard/gpio_keys.c
|
|
||||||
@@ -31,6 +31,8 @@
|
|
||||||
#include <linux/of_irq.h>
|
|
||||||
#include <linux/spinlock.h>
|
|
||||||
|
|
||||||
+#define WAKE_DEBOUNCE msecs_to_jiffies(1000)
|
|
||||||
+
|
|
||||||
struct gpio_button_data {
|
|
||||||
const struct gpio_keys_button *button;
|
|
||||||
struct input_dev *input;
|
|
||||||
@@ -44,10 +46,14 @@ struct gpio_button_data {
|
|
||||||
struct delayed_work work;
|
|
||||||
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
|
|
||||||
|
|
||||||
+ unsigned long resume_time; /* in jiffies, for wakeup buttons */
|
|
||||||
+
|
|
||||||
unsigned int irq;
|
|
||||||
spinlock_t lock;
|
|
||||||
bool disabled;
|
|
||||||
bool key_pressed;
|
|
||||||
+ bool suspended;
|
|
||||||
+ bool resume_time_valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gpio_keys_drvdata {
|
|
||||||
@@ -356,6 +362,27 @@ static struct attribute_group gpio_keys_attr_group = {
|
|
||||||
.attrs = gpio_keys_attrs,
|
|
||||||
};
|
|
||||||
|
|
||||||
+static bool gpio_keys_ignore_wakeup_button_press(struct gpio_button_data *bdata)
|
|
||||||
+{
|
|
||||||
+ unsigned long flags;
|
|
||||||
+ bool ret = false;
|
|
||||||
+
|
|
||||||
+ if (!bdata->button->wakeup)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ spin_lock_irqsave(&bdata->lock, flags);
|
|
||||||
+
|
|
||||||
+ if (bdata->suspended)
|
|
||||||
+ ret = true; /* Our resume method did not run yet */
|
|
||||||
+ else if (bdata->resume_time_valid &&
|
|
||||||
+ time_before(jiffies, bdata->resume_time + WAKE_DEBOUNCE))
|
|
||||||
+ ret = true; /* Assume this is a wakeup press and ignore */
|
|
||||||
+
|
|
||||||
+ spin_unlock_irqrestore(&bdata->lock, flags);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
|
|
||||||
{
|
|
||||||
const struct gpio_keys_button *button = bdata->button;
|
|
||||||
@@ -370,6 +397,9 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (state && gpio_keys_ignore_wakeup_button_press(bdata))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
if (type == EV_ABS) {
|
|
||||||
if (state)
|
|
||||||
input_event(input, type, button->code, button->value);
|
|
||||||
@@ -429,6 +459,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
|
|
||||||
|
|
||||||
BUG_ON(irq != bdata->irq);
|
|
||||||
|
|
||||||
+ if (gpio_keys_ignore_wakeup_button_press(bdata))
|
|
||||||
+ return IRQ_HANDLED;
|
|
||||||
+
|
|
||||||
spin_lock_irqsave(&bdata->lock, flags);
|
|
||||||
|
|
||||||
if (!bdata->key_pressed) {
|
|
||||||
@@ -848,13 +881,18 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
|
|
||||||
{
|
|
||||||
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
|
|
||||||
struct input_dev *input = ddata->input;
|
|
||||||
+ unsigned long flags;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (device_may_wakeup(dev)) {
|
|
||||||
for (i = 0; i < ddata->pdata->nbuttons; i++) {
|
|
||||||
struct gpio_button_data *bdata = &ddata->data[i];
|
|
||||||
- if (bdata->button->wakeup)
|
|
||||||
+ if (bdata->button->wakeup) {
|
|
||||||
+ spin_lock_irqsave(&bdata->lock, flags);
|
|
||||||
+ bdata->suspended = true;
|
|
||||||
+ spin_unlock_irqrestore(&bdata->lock, flags);
|
|
||||||
enable_irq_wake(bdata->irq);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mutex_lock(&input->mutex);
|
|
||||||
@@ -870,14 +908,21 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
|
|
||||||
{
|
|
||||||
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
|
|
||||||
struct input_dev *input = ddata->input;
|
|
||||||
+ unsigned long flags;
|
|
||||||
int error = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (device_may_wakeup(dev)) {
|
|
||||||
for (i = 0; i < ddata->pdata->nbuttons; i++) {
|
|
||||||
struct gpio_button_data *bdata = &ddata->data[i];
|
|
||||||
- if (bdata->button->wakeup)
|
|
||||||
+ if (bdata->button->wakeup) {
|
|
||||||
disable_irq_wake(bdata->irq);
|
|
||||||
+ spin_lock_irqsave(&bdata->lock, flags);
|
|
||||||
+ bdata->resume_time = jiffies;
|
|
||||||
+ bdata->resume_time_valid = true;
|
|
||||||
+ bdata->suspended = false;
|
|
||||||
+ spin_unlock_irqrestore(&bdata->lock, flags);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mutex_lock(&input->mutex);
|
|
||||||
--
|
|
||||||
2.13.0
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
From fd4fb1f6633b21042ff084868323e15e708fe1cd Mon Sep 17 00:00:00 2001
|
|
||||||
From: Hans de Goede <hdegoede@redhat.com>
|
|
||||||
Date: Sun, 1 Jan 2017 22:11:20 +0100
|
|
||||||
Subject: [PATCH 16/16] Input: silead: Do not try to directly access the GPIO
|
|
||||||
when using ACPI pm
|
|
||||||
|
|
||||||
On some x86 tablets we cannot directly access the GPIOs as they are
|
|
||||||
claimed by the ACPI tables, so check it the i2c client is not being
|
|
||||||
power-managed by ACPI before trying to get the power pin GPIO.
|
|
||||||
|
|
||||||
Note this is a workaround patch to fix this until Andy' gpiolib-ACPI
|
|
||||||
patches which make gpiolib more strict land, once those are landed this
|
|
||||||
patch is no longer needed.
|
|
||||||
|
|
||||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
||||||
---
|
|
||||||
drivers/input/touchscreen/silead.c | 22 ++++++++++++++++------
|
|
||||||
1 file changed, 16 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
|
|
||||||
index c0ba40c09699..30fba3cbe277 100644
|
|
||||||
--- a/drivers/input/touchscreen/silead.c
|
|
||||||
+++ b/drivers/input/touchscreen/silead.c
|
|
||||||
@@ -517,12 +518,21 @@ static int silead_ts_probe(struct i2c_client *client,
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
- /* Power GPIO pin */
|
|
||||||
- data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
|
|
||||||
- if (IS_ERR(data->gpio_power)) {
|
|
||||||
- if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
|
|
||||||
- dev_err(dev, "Shutdown GPIO request failed\n");
|
|
||||||
- return PTR_ERR(data->gpio_power);
|
|
||||||
+ /*
|
|
||||||
+ * If device power is not managed by ACPI, get the power_gpio
|
|
||||||
+ * and manage it ourselves.
|
|
||||||
+ */
|
|
||||||
+#ifdef CONFIG_ACPI
|
|
||||||
+ if (!acpi_bus_power_manageable(ACPI_HANDLE(dev)))
|
|
||||||
+#endif
|
|
||||||
+ {
|
|
||||||
+ data->gpio_power = devm_gpiod_get_optional(dev, "power",
|
|
||||||
+ GPIOD_OUT_LOW);
|
|
||||||
+ if (IS_ERR(data->gpio_power)) {
|
|
||||||
+ if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
|
|
||||||
+ dev_err(dev, "Power GPIO request failed\n");
|
|
||||||
+ return PTR_ERR(data->gpio_power);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
error = silead_ts_setup(client);
|
|
||||||
--
|
|
||||||
2.13.0
|
|
||||||
|
|
13
kernel.spec
13
kernel.spec
@ -637,14 +637,15 @@ Patch502: CVE-2017-7477.patch
|
|||||||
|
|
||||||
# 600 - Patches for improved Bay and Cherry Trail device support
|
# 600 - Patches for improved Bay and Cherry Trail device support
|
||||||
# Below patches are submitted upstream, awaiting review / merging
|
# Below patches are submitted upstream, awaiting review / merging
|
||||||
|
Patch601: 0001-Input-gpio_keys-Allow-suppression-of-input-events-fo.patch
|
||||||
|
Patch602: 0002-Input-soc_button_array-Suppress-power-button-presses.patch
|
||||||
Patch610: 0010-Input-silead-Add-support-for-capactive-home-button-f.patch
|
Patch610: 0010-Input-silead-Add-support-for-capactive-home-button-f.patch
|
||||||
Patch611: 0011-Input-goodix-Add-support-for-capacitive-home-button.patch
|
Patch611: 0011-Input-goodix-Add-support-for-capacitive-home-button.patch
|
||||||
# This either needs to be removed or rebased
|
# These patches are queued for 4.14 and can be dropped on rebase to 4.14-rc1
|
||||||
# Patch612: 0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch
|
Patch603: 0001-power-supply-max17042_battery-Add-support-for-ACPI-e.patch
|
||||||
|
Patch604: 0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch
|
||||||
Patch613: 0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch
|
Patch613: 0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch
|
||||||
Patch615: 0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch
|
Patch615: 0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch
|
||||||
# Small workaround patches for issues with a more comprehensive fix in -next
|
|
||||||
Patch616: 0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch
|
|
||||||
|
|
||||||
# rhbz 1476467
|
# rhbz 1476467
|
||||||
Patch617: Fix-for-module-sig-verification.patch
|
Patch617: Fix-for-module-sig-verification.patch
|
||||||
@ -2209,6 +2210,10 @@ fi
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Aug 31 2017 Hans de Goede <jwrdegoede@fedoraproject.org>
|
||||||
|
- Update patches for power-button wakeup issues on Bay / Cherry Trail devices
|
||||||
|
- Add patches to fix an IRQ storm on devices with a MAX17042 fuel-gauge
|
||||||
|
|
||||||
* Wed Aug 30 2017 Peter Robinson <pbrobinson@fedoraproject.org>
|
* Wed Aug 30 2017 Peter Robinson <pbrobinson@fedoraproject.org>
|
||||||
- Fix for QCom Dragonboard USB
|
- Fix for QCom Dragonboard USB
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user