#include <media/v4l2-ioctl.h>
 #include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
+#include <dt-bindings/input/atmel-maxtouch.h>
 
 /* Firmware files */
 #define MXT_FW_NAME            "maxtouch.fw"
 #define MXT_CRC_TIMEOUT                1000    /* msec */
 #define MXT_FW_RESET_TIME      3000    /* msec */
 #define MXT_FW_CHG_TIMEOUT     300     /* msec */
+#define MXT_WAKEUP_TIME                25      /* msec */
 
 /* Command to unlock bootloader */
 #define MXT_UNLOCK_CMD_MSB     0xaa
        struct mxt_dbg dbg;
        struct regulator_bulk_data regulators[2];
        struct gpio_desc *reset_gpio;
+       struct gpio_desc *wake_gpio;
        bool use_retrigen_workaround;
 
        /* Cached parameters from object table */
        unsigned int t19_num_keys;
 
        enum mxt_suspend_mode suspend_mode;
+
+       u32 wakeup_method;
 };
 
 struct mxt_vb2_buffer {
        return mxt_bootloader_write(data, buf, sizeof(buf));
 }
 
+static bool mxt_wakeup_toggle(struct i2c_client *client,
+                             bool wake_up, bool in_i2c)
+{
+       struct mxt_data *data = i2c_get_clientdata(client);
+
+       switch (data->wakeup_method) {
+       case ATMEL_MXT_WAKEUP_I2C_SCL:
+               if (!in_i2c)
+                       return false;
+               break;
+
+       case ATMEL_MXT_WAKEUP_GPIO:
+               if (in_i2c)
+                       return false;
+
+               gpiod_set_value(data->wake_gpio, wake_up);
+               break;
+
+       default:
+               return false;
+       }
+
+       if (wake_up) {
+               dev_dbg(&client->dev, "waking up controller\n");
+
+               msleep(MXT_WAKEUP_TIME);
+       }
+
+       return true;
+}
+
 static int __mxt_read_reg(struct i2c_client *client,
                               u16 reg, u16 len, void *val)
 {
        struct i2c_msg xfer[2];
+       bool retried = false;
        u8 buf[2];
        int ret;
 
        xfer[1].len = len;
        xfer[1].buf = val;
 
+retry:
        ret = i2c_transfer(client->adapter, xfer, 2);
        if (ret == 2) {
                ret = 0;
+       } else if (!retried && mxt_wakeup_toggle(client, true, true)) {
+               retried = true;
+               goto retry;
        } else {
                if (ret >= 0)
                        ret = -EIO;
 static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
                           const void *val)
 {
+       bool retried = false;
        u8 *buf;
        size_t count;
        int ret;
        buf[1] = (reg >> 8) & 0xff;
        memcpy(&buf[2], val, len);
 
+retry:
        ret = i2c_master_send(client, buf, count);
        if (ret == count) {
                ret = 0;
+       } else if (!retried && mxt_wakeup_toggle(client, true, true)) {
+               retried = true;
+               goto retry;
        } else {
                if (ret >= 0)
                        ret = -EIO;
 
 static void mxt_start(struct mxt_data *data)
 {
+       mxt_wakeup_toggle(data->client, true, false);
+
        switch (data->suspend_mode) {
        case MXT_SUSPEND_T9_CTRL:
                mxt_soft_reset(data);
                mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
                break;
        }
+
+       mxt_wakeup_toggle(data->client, false, false);
 }
 
 static int mxt_input_open(struct input_dev *dev)
                return error;
        }
 
+       /* Request the WAKE line as asserted so we go out of sleep */
+       data->wake_gpio = devm_gpiod_get_optional(&client->dev,
+                                                 "wake", GPIOD_OUT_HIGH);
+       if (IS_ERR(data->wake_gpio)) {
+               error = PTR_ERR(data->wake_gpio);
+               dev_err(&client->dev, "Failed to get wake gpio: %d\n", error);
+               return error;
+       }
+
        error = devm_request_threaded_irq(&client->dev, client->irq,
                                          NULL, mxt_interrupt, IRQF_ONESHOT,
                                          client->name, data);
                msleep(MXT_RESET_INVALID_CHG);
        }
 
+       /*
+        * Controllers like mXT1386 have a dedicated WAKE line that could be
+        * connected to a GPIO or to I2C SCL pin, or permanently asserted low.
+        *
+        * This WAKE line is used for waking controller from a deep-sleep and
+        * it needs to be asserted low for 25 milliseconds before I2C transfers
+        * could be accepted by controller if it was in a deep-sleep mode.
+        * Controller will go into sleep automatically after 2 seconds of
+        * inactivity if WAKE line is deasserted and deep sleep is activated.
+        *
+        * If WAKE line is connected to I2C SCL pin, then the first I2C transfer
+        * will get an instant NAK and transfer needs to be retried after 25ms.
+        *
+        * If WAKE line is connected to a GPIO line, the line must be asserted
+        * 25ms before the host attempts to communicate with the controller.
+        */
+       device_property_read_u32(&client->dev, "atmel,wakeup-method",
+                                &data->wakeup_method);
+
        error = mxt_initialize(data);
        if (error)
                goto err_disable_regulators;