Skip to content

Commit

Permalink
Input: atmel_mxt_ts - implement I2C retries
Browse files Browse the repository at this point in the history
Some maXTouch chips (eg mXT1386) will not respond on the first I2C request
when they are in a sleep state. It must be retried after a delay for the
chip to wake up.

Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk>
Acked-by: Yufeng Shen <miletus@chromium.org>
  • Loading branch information
ndyer committed Apr 26, 2016
1 parent 64c9dad commit 63fd7a2
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions drivers/input/touchscreen/atmel_mxt_ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ enum t100_type {
#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 */
#define MXT_REGULATOR_DELAY 150 /* msec */
#define MXT_CHG_DELAY 100 /* msec */
#define MXT_POWERON_DELAY 150 /* msec */
Expand Down Expand Up @@ -654,6 +655,7 @@ static int __mxt_read_reg(struct i2c_client *client,
struct i2c_msg xfer[2];
u8 buf[2];
int ret;
bool retry = false;

buf[0] = reg & 0xff;
buf[1] = (reg >> 8) & 0xff;
Expand All @@ -670,17 +672,22 @@ static int __mxt_read_reg(struct i2c_client *client,
xfer[1].len = len;
xfer[1].buf = val;

ret = i2c_transfer(client->adapter, xfer, 2);
if (ret == 2) {
ret = 0;
} else {
if (ret >= 0)
ret = -EIO;
dev_err(&client->dev, "%s: i2c transfer failed (%d)\n",
__func__, ret);
retry_read:
ret = i2c_transfer(client->adapter, xfer, ARRAY_SIZE(xfer));
if (ret != ARRAY_SIZE(xfer)) {
if (!retry) {
dev_dbg(&client->dev, "%s: i2c retry\n", __func__);
msleep(MXT_WAKEUP_TIME);
retry = true;
goto retry_read;
} else {
dev_err(&client->dev, "%s: i2c transfer failed (%d)\n",
__func__, ret);
return -EIO;
}
}

return ret;
return 0;
}

static int mxt_read_blks(struct mxt_data *data, u16 start, u16 count, u8 *buf)
Expand Down Expand Up @@ -710,6 +717,7 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
u8 *buf;
size_t count;
int ret;
bool retry = false;

count = len + 2;
buf = kmalloc(count, GFP_KERNEL);
Expand All @@ -720,14 +728,21 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
buf[1] = (reg >> 8) & 0xff;
memcpy(&buf[2], val, len);

retry_write:
ret = i2c_master_send(client, buf, count);
if (ret == count) {
ret = 0;
} else {
if (ret >= 0)
if (ret != count) {
if (!retry) {
dev_dbg(&client->dev, "%s: i2c retry\n", __func__);
msleep(MXT_WAKEUP_TIME);
retry = true;
goto retry_write;
} else {
dev_err(&client->dev, "%s: i2c send failed (%d)\n",
__func__, ret);
ret = -EIO;
dev_err(&client->dev, "%s: i2c send failed (%d)\n",
__func__, ret);
}
} else {
ret = 0;
}

kfree(buf);
Expand Down

0 comments on commit 63fd7a2

Please sign in to comment.