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 | ||||
| # 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 | ||||
| Patch611: 0011-Input-goodix-Add-support-for-capacitive-home-button.patch | ||||
| # This either needs to be removed or rebased | ||||
| # Patch612: 0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch | ||||
| # These patches are queued for 4.14 and can be dropped on rebase to 4.14-rc1 | ||||
| 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 | ||||
| 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 | ||||
| Patch617: Fix-for-module-sig-verification.patch | ||||
| @ -2209,6 +2210,10 @@ fi | ||||
| # | ||||
| # | ||||
| %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> | ||||
| - Fix for QCom Dragonboard USB | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user