Input: synaptics-rmi4 - handle reset delay when using SMBus trsnsport
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 14 Oct 2023 00:29:57 +0000 (17:29 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 14 Oct 2023 00:59:19 +0000 (17:59 -0700)
Touch controllers need some time after receiving reset command for the
firmware to finish re-initializing and be ready to respond to commands
from the host. The driver already had handling for the post-reset delay
for I2C and SPI transports, this change adds the handling to
SMBus-connected devices.

SMBus devices are peculiar because they implement legacy PS/2
compatibility mode, so reset is actually issued by psmouse driver on the
associated serio port, after which the control is passed to the RMI4
driver with SMBus companion device.

Note that originally the delay was added to psmouse driver in
92e24e0e57f7 ("Input: psmouse - add delay when deactivating for SMBus
mode"), but that resulted in an unwanted delay in "fast" reconnect
handler for the serio port, so it was decided to revert the patch and
have the delay being handled in the RMI4 driver, similar to the other
transports.

Tested-by: Jeffery Miller <jefferymiller@google.com>
Link: https://lore.kernel.org/r/ZR1yUFJ8a9Zt606N@penguin
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/mouse/synaptics.c
drivers/input/rmi4/rmi_smbus.c

index cefc74b3b34b12eb8720406180383e37d38d93c8..22d16d80efb938b5ae9576d5bb064900af343499 100644 (file)
@@ -1753,6 +1753,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse,
                psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) &&
                !SYN_CAP_EXT_BUTTONS_STICK(info->ext_cap_10);
        const struct rmi_device_platform_data pdata = {
+               .reset_delay_ms = 30,
                .sensor_pdata = {
                        .sensor_type = rmi_sensor_touchpad,
                        .axis_align.flip_y = true,
index 7059a2762aebc1f2a4b09908f214d04e6ab54ee8..b0b099b5528a8b78fbe60b0db9a79b2751a74edb 100644 (file)
@@ -235,12 +235,29 @@ static void rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb)
 
 static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb)
 {
-       int retval;
+       struct i2c_client *client = rmi_smb->client;
+       int smbus_version;
+
+       /*
+        * psmouse driver resets the controller, we only need to wait
+        * to give the firmware chance to fully reinitialize.
+        */
+       if (rmi_smb->xport.pdata.reset_delay_ms)
+               msleep(rmi_smb->xport.pdata.reset_delay_ms);
 
        /* we need to get the smbus version to activate the touchpad */
-       retval = rmi_smb_get_version(rmi_smb);
-       if (retval < 0)
-               return retval;
+       smbus_version = rmi_smb_get_version(rmi_smb);
+       if (smbus_version < 0)
+               return smbus_version;
+
+       rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d",
+               smbus_version);
+
+       if (smbus_version != 2 && smbus_version != 3) {
+               dev_err(&client->dev, "Unrecognized SMB version %d\n",
+                               smbus_version);
+               return -ENODEV;
+       }
 
        return 0;
 }
@@ -253,11 +270,10 @@ static int rmi_smb_reset(struct rmi_transport_dev *xport, u16 reset_addr)
        rmi_smb_clear_state(rmi_smb);
 
        /*
-        * we do not call the actual reset command, it has to be handled in
-        * PS/2 or there will be races between PS/2 and SMBus.
-        * PS/2 should ensure that a psmouse_reset is called before
-        * intializing the device and after it has been removed to be in a known
-        * state.
+        * We do not call the actual reset command, it has to be handled in
+        * PS/2 or there will be races between PS/2 and SMBus. PS/2 should
+        * ensure that a psmouse_reset is called before initializing the
+        * device and after it has been removed to be in a known state.
         */
        return rmi_smb_enable_smbus_mode(rmi_smb);
 }
@@ -272,7 +288,6 @@ static int rmi_smb_probe(struct i2c_client *client)
 {
        struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev);
        struct rmi_smb_xport *rmi_smb;
-       int smbus_version;
        int error;
 
        if (!pdata) {
@@ -311,18 +326,9 @@ static int rmi_smb_probe(struct i2c_client *client)
        rmi_smb->xport.proto_name = "smb";
        rmi_smb->xport.ops = &rmi_smb_ops;
 
-       smbus_version = rmi_smb_get_version(rmi_smb);
-       if (smbus_version < 0)
-               return smbus_version;
-
-       rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d",
-               smbus_version);
-
-       if (smbus_version != 2 && smbus_version != 3) {
-               dev_err(&client->dev, "Unrecognized SMB version %d\n",
-                               smbus_version);
-               return -ENODEV;
-       }
+       error = rmi_smb_enable_smbus_mode(rmi_smb);
+       if (error)
+               return error;
 
        i2c_set_clientdata(client, rmi_smb);