summaryrefslogtreecommitdiffstats
path: root/0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch
diff options
context:
space:
mode:
Diffstat (limited to '0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch')
-rw-r--r--0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch80
1 files changed, 80 insertions, 0 deletions
diff --git a/0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch b/0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch
new file mode 100644
index 000000000..6daecaf4d
--- /dev/null
+++ b/0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch
@@ -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
+