|
Takashi Iwai |
2bec1a |
From e479187748a8f151a85116a7091c599b121fdea5 Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
2bec1a |
From: Hans de Goede <hdegoede@redhat.com>
|
|
Takashi Iwai |
2bec1a |
Date: Fri, 9 Apr 2021 22:29:49 -0700
|
|
Takashi Iwai |
2bec1a |
Subject: [PATCH] Input: silead - add workaround for x86 BIOS-es which bring the chip up in a stuck state
|
|
Takashi Iwai |
2bec1a |
Git-commit: e479187748a8f151a85116a7091c599b121fdea5
|
|
Takashi Iwai |
2bec1a |
Patch-mainline: v5.13-rc1
|
|
Takashi Iwai |
2bec1a |
References: git-fixes
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
Some buggy BIOS-es bring up the touchscreen-controller in a stuck
|
|
Takashi Iwai |
2bec1a |
state where it blocks the I2C bus. Specifically this happens on
|
|
Takashi Iwai |
2bec1a |
the Jumper EZpad 7 tablet model.
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
After much poking at this problem I have found that the following steps
|
|
Takashi Iwai |
2bec1a |
are necessary to unstuck the chip / bus:
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
1. Turn off the Silead chip.
|
|
Takashi Iwai |
2bec1a |
2. Try to do an I2C transfer with the chip, this will fail in response to
|
|
Takashi Iwai |
2bec1a |
which the I2C-bus-driver will call: i2c_recover_bus() which will unstuck
|
|
Takashi Iwai |
2bec1a |
the I2C-bus. Note the unstuck-ing of the I2C bus only works if we first
|
|
Takashi Iwai |
2bec1a |
drop the chip of the bus by turning it off.
|
|
Takashi Iwai |
2bec1a |
3. Turn the chip back on.
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
On the x86/ACPI systems were this problem is seen, step 1. and 3. require
|
|
Takashi Iwai |
2bec1a |
making ACPI calls and dealing with ACPI Power Resources. This commit adds
|
|
Takashi Iwai |
2bec1a |
a workaround which runtime-suspends the chip to turn it off, leaving it up
|
|
Takashi Iwai |
2bec1a |
to the ACPI subsystem to deal with all the ACPI specific details.
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
There is no good way to detect this bug, so the workaround gets activated
|
|
Takashi Iwai |
2bec1a |
by a new "silead,stuck-controller-bug" boolean device-property. Since this
|
|
Takashi Iwai |
2bec1a |
is only used on x86/ACPI, this will be set by model specific device-props
|
|
Takashi Iwai |
2bec1a |
set by drivers/platform/x86/touchscreen_dmi.c. Therefor this new
|
|
Takashi Iwai |
2bec1a |
device-property is not documented in the DT-bindings.
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
Dmesg will contain the following messages on systems where the workaround
|
|
Takashi Iwai |
2bec1a |
is activated:
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
[ 54.309029] silead_ts i2c-MSSL1680:00: [Firmware Bug]: Stuck I2C bus: please ignore the next 'controller timed out' error
|
|
Takashi Iwai |
2bec1a |
[ 55.373593] i2c_designware 808622C1:04: controller timed out
|
|
Takashi Iwai |
2bec1a |
[ 55.582186] silead_ts i2c-MSSL1680:00: Silead chip ID: 0x80360000
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Takashi Iwai |
2bec1a |
Link: https://lore.kernel.org/r/20210405202745.16777-1-hdegoede@redhat.com
|
|
Takashi Iwai |
2bec1a |
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
|
Takashi Iwai |
2bec1a |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
---
|
|
Takashi Iwai |
2bec1a |
drivers/input/touchscreen/silead.c | 44 +++++++++++++++++++++++++++---
|
|
Takashi Iwai |
2bec1a |
1 file changed, 40 insertions(+), 4 deletions(-)
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
|
|
Takashi Iwai |
2bec1a |
index 32725d7422de..1ee760bac0cf 100644
|
|
Takashi Iwai |
2bec1a |
--- a/drivers/input/touchscreen/silead.c
|
|
Takashi Iwai |
2bec1a |
+++ b/drivers/input/touchscreen/silead.c
|
|
Takashi Iwai |
2bec1a |
@@ -20,6 +20,7 @@
|
|
Takashi Iwai |
2bec1a |
#include <linux/input/mt.h>
|
|
Takashi Iwai |
2bec1a |
#include <linux/input/touchscreen.h>
|
|
Takashi Iwai |
2bec1a |
#include <linux/pm.h>
|
|
Takashi Iwai |
2bec1a |
+#include <linux/pm_runtime.h>
|
|
Takashi Iwai |
2bec1a |
#include <linux/irq.h>
|
|
Takashi Iwai |
2bec1a |
#include <linux/regulator/consumer.h>
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
@@ -335,10 +336,8 @@ static int silead_ts_get_id(struct i2c_client *client)
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_ID,
|
|
Takashi Iwai |
2bec1a |
sizeof(chip_id), (u8 *)&chip_id);
|
|
Takashi Iwai |
2bec1a |
- if (error < 0) {
|
|
Takashi Iwai |
2bec1a |
- dev_err(&client->dev, "Chip ID read error %d\n", error);
|
|
Takashi Iwai |
2bec1a |
+ if (error < 0)
|
|
Takashi Iwai |
2bec1a |
return error;
|
|
Takashi Iwai |
2bec1a |
- }
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
data->chip_id = le32_to_cpu(chip_id);
|
|
Takashi Iwai |
2bec1a |
dev_info(&client->dev, "Silead chip ID: 0x%8X", data->chip_id);
|
|
Takashi Iwai |
2bec1a |
@@ -351,12 +350,49 @@ static int silead_ts_setup(struct i2c_client *client)
|
|
Takashi Iwai |
2bec1a |
int error;
|
|
Takashi Iwai |
2bec1a |
u32 status;
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
+ /*
|
|
Takashi Iwai |
2bec1a |
+ * Some buggy BIOS-es bring up the chip in a stuck state where it
|
|
Takashi Iwai |
2bec1a |
+ * blocks the I2C bus. The following steps are necessary to
|
|
Takashi Iwai |
2bec1a |
+ * unstuck the chip / bus:
|
|
Takashi Iwai |
2bec1a |
+ * 1. Turn off the Silead chip.
|
|
Takashi Iwai |
2bec1a |
+ * 2. Try to do an I2C transfer with the chip, this will fail in
|
|
Takashi Iwai |
2bec1a |
+ * response to which the I2C-bus-driver will call:
|
|
Takashi Iwai |
2bec1a |
+ * i2c_recover_bus() which will unstuck the I2C-bus. Note the
|
|
Takashi Iwai |
2bec1a |
+ * unstuck-ing of the I2C bus only works if we first drop the
|
|
Takashi Iwai |
2bec1a |
+ * chip off the bus by turning it off.
|
|
Takashi Iwai |
2bec1a |
+ * 3. Turn the chip back on.
|
|
Takashi Iwai |
2bec1a |
+ *
|
|
Takashi Iwai |
2bec1a |
+ * On the x86/ACPI systems were this problem is seen, step 1. and
|
|
Takashi Iwai |
2bec1a |
+ * 3. require making ACPI calls and dealing with ACPI Power
|
|
Takashi Iwai |
2bec1a |
+ * Resources. The workaround below runtime-suspends the chip to
|
|
Takashi Iwai |
2bec1a |
+ * turn it off, leaving it up to the ACPI subsystem to deal with
|
|
Takashi Iwai |
2bec1a |
+ * this.
|
|
Takashi Iwai |
2bec1a |
+ */
|
|
Takashi Iwai |
2bec1a |
+
|
|
Takashi Iwai |
2bec1a |
+ if (device_property_read_bool(&client->dev,
|
|
Takashi Iwai |
2bec1a |
+ "silead,stuck-controller-bug")) {
|
|
Takashi Iwai |
2bec1a |
+ pm_runtime_set_active(&client->dev);
|
|
Takashi Iwai |
2bec1a |
+ pm_runtime_enable(&client->dev);
|
|
Takashi Iwai |
2bec1a |
+ pm_runtime_allow(&client->dev);
|
|
Takashi Iwai |
2bec1a |
+
|
|
Takashi Iwai |
2bec1a |
+ pm_runtime_suspend(&client->dev);
|
|
Takashi Iwai |
2bec1a |
+
|
|
Takashi Iwai |
2bec1a |
+ dev_warn(&client->dev, FW_BUG "Stuck I2C bus: please ignore the next 'controller timed out' error\n");
|
|
Takashi Iwai |
2bec1a |
+ silead_ts_get_id(client);
|
|
Takashi Iwai |
2bec1a |
+
|
|
Takashi Iwai |
2bec1a |
+ /* The forbid will also resume the device */
|
|
Takashi Iwai |
2bec1a |
+ pm_runtime_forbid(&client->dev);
|
|
Takashi Iwai |
2bec1a |
+ pm_runtime_disable(&client->dev);
|
|
Takashi Iwai |
2bec1a |
+ }
|
|
Takashi Iwai |
2bec1a |
+
|
|
Takashi Iwai |
2bec1a |
silead_ts_set_power(client, SILEAD_POWER_OFF);
|
|
Takashi Iwai |
2bec1a |
silead_ts_set_power(client, SILEAD_POWER_ON);
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
error = silead_ts_get_id(client);
|
|
Takashi Iwai |
2bec1a |
- if (error)
|
|
Takashi Iwai |
2bec1a |
+ if (error) {
|
|
Takashi Iwai |
2bec1a |
+ dev_err(&client->dev, "Chip ID read error %d\n", error);
|
|
Takashi Iwai |
2bec1a |
return error;
|
|
Takashi Iwai |
2bec1a |
+ }
|
|
Takashi Iwai |
2bec1a |
|
|
Takashi Iwai |
2bec1a |
error = silead_ts_init(client);
|
|
Takashi Iwai |
2bec1a |
if (error)
|
|
Takashi Iwai |
2bec1a |
--
|
|
Takashi Iwai |
2bec1a |
2.26.2
|
|
Takashi Iwai |
2bec1a |
|