81 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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
 | |
| 
 |