#include <linux/input/mt.h>
 #include <linux/input/touchscreen.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/irq.h>
 #include <linux/regulator/consumer.h>
 
 
        error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_ID,
                                              sizeof(chip_id), (u8 *)&chip_id);
-       if (error < 0) {
-               dev_err(&client->dev, "Chip ID read error %d\n", error);
+       if (error < 0)
                return error;
-       }
 
        data->chip_id = le32_to_cpu(chip_id);
        dev_info(&client->dev, "Silead chip ID: 0x%8X", data->chip_id);
        int error;
        u32 status;
 
+       /*
+        * Some buggy BIOS-es bring up the chip in a stuck state where it
+        * blocks the I2C bus. The following steps are necessary to
+        * unstuck the chip / bus:
+        * 1. Turn off the Silead chip.
+        * 2. Try to do an I2C transfer with the chip, this will fail in
+        *    response to which the I2C-bus-driver will call:
+        *    i2c_recover_bus() which will unstuck the I2C-bus. Note the
+        *    unstuck-ing of the I2C bus only works if we first drop the
+        *    chip off the bus by turning it off.
+        * 3. Turn the chip back on.
+        *
+        * On the x86/ACPI systems were this problem is seen, step 1. and
+        * 3. require making ACPI calls and dealing with ACPI Power
+        * Resources. The workaround below runtime-suspends the chip to
+        * turn it off, leaving it up to the ACPI subsystem to deal with
+        * this.
+        */
+
+       if (device_property_read_bool(&client->dev,
+                                     "silead,stuck-controller-bug")) {
+               pm_runtime_set_active(&client->dev);
+               pm_runtime_enable(&client->dev);
+               pm_runtime_allow(&client->dev);
+
+               pm_runtime_suspend(&client->dev);
+
+               dev_warn(&client->dev, FW_BUG "Stuck I2C bus: please ignore the next 'controller timed out' error\n");
+               silead_ts_get_id(client);
+
+               /* The forbid will also resume the device */
+               pm_runtime_forbid(&client->dev);
+               pm_runtime_disable(&client->dev);
+       }
+
        silead_ts_set_power(client, SILEAD_POWER_OFF);
        silead_ts_set_power(client, SILEAD_POWER_ON);
 
        error = silead_ts_get_id(client);
-       if (error)
+       if (error) {
+               dev_err(&client->dev, "Chip ID read error %d\n", error);
                return error;
+       }
 
        error = silead_ts_init(client);
        if (error)