summaryrefslogtreecommitdiff
path: root/drivers/hid/i2c-hid/i2c-hid-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/i2c-hid/i2c-hid-core.c')
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 2df1ab3c31cc..39ed58a8a04c 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -164,6 +164,24 @@ static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
return quirks;
}
+static int i2c_hid_probe_address(struct i2c_hid *ihid)
+{
+ int ret;
+
+ /*
+ * Some STM-based devices need 400µs after a rising clock edge to wake
+ * from deep sleep, in which case the first read will fail. Try after a
+ * short sleep to see if the device came alive on the bus. Certain
+ * Weida Tech devices also need this.
+ */
+ ret = i2c_smbus_read_byte(ihid->client);
+ if (ret < 0) {
+ usleep_range(400, 500);
+ ret = i2c_smbus_read_byte(ihid->client);
+ }
+ return ret < 0 ? ret : 0;
+}
+
static int i2c_hid_xfer(struct i2c_hid *ihid,
u8 *send_buf, int send_len, u8 *recv_buf, int recv_len)
{
@@ -1014,8 +1032,7 @@ static int __i2c_hid_core_probe(struct i2c_hid *ihid)
struct hid_device *hid = ihid->hid;
int ret;
- /* Make sure there is something at this address */
- ret = i2c_smbus_read_byte(client);
+ ret = i2c_hid_probe_address(ihid);
if (ret < 0) {
i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
return -ENXIO;