Commit 96d3098d authored by Hans de Goede's avatar Hans de Goede Committed by Jiri Kosina

HID: i2c-hid: Split i2c_hid_hwreset() in start() and finish() functions

Split i2c_hid_hwreset() into:

i2c_hid_start_hwreset() which sends the PWR_ON and reset commands; and
i2c_hid_finish_hwreset() which actually waits for the reset to complete.

This is a preparation patch for removing the need for
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET by making i2c-hid behave
more like Windows.

No functional changes intended.
Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.com>
parent f023605d
...@@ -426,7 +426,7 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state) ...@@ -426,7 +426,7 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
return ret; return ret;
} }
static int i2c_hid_hwreset(struct i2c_hid *ihid) static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
{ {
size_t length = 0; size_t length = 0;
int ret; int ret;
...@@ -438,11 +438,11 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid) ...@@ -438,11 +438,11 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid)
* being reset. Otherwise we may lose the reset complete * being reset. Otherwise we may lose the reset complete
* interrupt. * interrupt.
*/ */
mutex_lock(&ihid->reset_lock); lockdep_assert_held(&ihid->reset_lock);
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON); ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
if (ret) if (ret)
goto err_unlock; return ret;
/* Prepare reset command. Command register goes first. */ /* Prepare reset command. Command register goes first. */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
...@@ -460,6 +460,18 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid) ...@@ -460,6 +460,18 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid)
goto err_clear_reset; goto err_clear_reset;
} }
return 0;
err_clear_reset:
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
return ret;
}
static int i2c_hid_finish_hwreset(struct i2c_hid *ihid)
{
int ret = 0;
i2c_hid_dbg(ihid, "%s: waiting...\n", __func__); i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) { if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) {
...@@ -477,14 +489,11 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid) ...@@ -477,14 +489,11 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid)
if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET)) if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET))
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON); ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
mutex_unlock(&ihid->reset_lock);
return ret; return ret;
err_clear_reset: err_clear_reset:
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags); clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP); i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
err_unlock:
mutex_unlock(&ihid->reset_lock);
return ret; return ret;
} }
...@@ -731,7 +740,11 @@ static int i2c_hid_parse(struct hid_device *hid) ...@@ -731,7 +740,11 @@ static int i2c_hid_parse(struct hid_device *hid)
} }
do { do {
ret = i2c_hid_hwreset(ihid); mutex_lock(&ihid->reset_lock);
ret = i2c_hid_start_hwreset(ihid);
if (ret == 0)
ret = i2c_hid_finish_hwreset(ihid);
mutex_unlock(&ihid->reset_lock);
if (ret) if (ret)
msleep(1000); msleep(1000);
} while (tries-- > 0 && ret); } while (tries-- > 0 && ret);
...@@ -974,10 +987,15 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid) ...@@ -974,10 +987,15 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
* However some ALPS touchpads generate IRQ storm without reset, so * However some ALPS touchpads generate IRQ storm without reset, so
* let's still reset them here. * let's still reset them here.
*/ */
if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME) if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME) {
ret = i2c_hid_hwreset(ihid); mutex_lock(&ihid->reset_lock);
else ret = i2c_hid_start_hwreset(ihid);
if (ret == 0)
ret = i2c_hid_finish_hwreset(ihid);
mutex_unlock(&ihid->reset_lock);
} else {
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON); ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
}
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment