MLK-17312-5 usb: cdns3: improve the role switch process
authorPeter Chen <peter.chen@nxp.com>
Tue, 2 Jan 2018 06:45:15 +0000 (14:45 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:52:30 +0000 (14:52 -0500)
Current design tries to switch role no matter it is a dual-role device
or a single-role device. It produces extra switch process, and have an
error message at console when tries to start a non-exist role.

In this commit, we do below changes
- The role switch work queue is only for dual-role or peripheral-only
device.
- For peripheral-only device, we need to switch role to CDNS3_ROLE_END
since we need to close vbus and turn off clocks at this role when the
cable is disconnected from the host; And we do noop when the external
cable indicates we are host.

Acked-by: Jun Li <jun.li@nxp.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
drivers/usb/cdns3/core.c

index 8b0f5da..d531f3b 100644 (file)
@@ -420,6 +420,9 @@ static int cdns3_do_role_switch(struct cdns3 *cdns, enum cdns3_roles role)
  *
  * @work: work queue item structure
  *
+ * Handles below events:
+ * - Role switch for dual-role devices
+ * - CDNS3_ROLE_GADGET <--> CDNS3_ROLE_END for peripheral-only devices
  */
 static void cdns3_role_switch(struct work_struct *work)
 {
@@ -430,9 +433,13 @@ static void cdns3_role_switch(struct work_struct *work)
        host = extcon_get_state(cdns->extcon, EXTCON_USB_HOST);
        device = extcon_get_state(cdns->extcon, EXTCON_USB);
 
-       if (host)
-               cdns3_do_role_switch(cdns, CDNS3_ROLE_HOST);
-       else if (device)
+       if (host) {
+               if (cdns->roles[CDNS3_ROLE_HOST])
+                       cdns3_do_role_switch(cdns, CDNS3_ROLE_HOST);
+               return;
+       }
+
+       if (device)
                cdns3_do_role_switch(cdns, CDNS3_ROLE_GADGET);
        else
                cdns3_do_role_switch(cdns, CDNS3_ROLE_END);
@@ -567,15 +574,17 @@ static int cdns3_probe(struct platform_device *pdev)
        if (ret)
                goto err1;
 
-       INIT_WORK(&cdns->role_switch_wq, cdns3_role_switch);
-       ret = cdns3_register_extcon(cdns);
-       if (ret)
-               goto err2;
-
        ret = cdns3_core_init_role(cdns);
        if (ret)
                goto err2;
 
+       if (cdns->roles[CDNS3_ROLE_GADGET]) {
+               INIT_WORK(&cdns->role_switch_wq, cdns3_role_switch);
+               ret = cdns3_register_extcon(cdns);
+               if (ret)
+                       goto err3;
+       }
+
        cdns->role = cdns3_get_role(cdns);
        dev_dbg(dev, "the init role is %d\n", cdns->role);
        cdns_set_role(cdns, cdns->role);