Register with OTG core when gadget function driver
is available and unregister when function driver is unbound.

Ignore softconnect sysfs control when we're in OTG
mode as OTG FSM takes care of gadget softconnect using
the b_bus_req mechanism.

Signed-off-by: Roger Quadros <rog...@ti.com>
---
 drivers/usb/gadget/udc/udc-core.c | 34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/gadget/udc/udc-core.c 
b/drivers/usb/gadget/udc/udc-core.c
index 3aa5dd5..ad162e5 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -28,6 +28,7 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb.h>
+#include <linux/usb/usb-otg.h>
 
 /**
  * struct usb_udc - describes one usb device controller
@@ -35,6 +36,7 @@
  * @dev - the child device to the actual controller
  * @gadget - the gadget. For use by the class code
  * @list - for use by the udc class driver
+ * @is_otg - we're registered with OTG core and it takes care of UDC start/stop
  *
  * This represents the internal data structure which is used by the UDC-class
  * to hold information about udc driver and gadget together.
@@ -44,6 +46,7 @@ struct usb_udc {
        struct usb_gadget               *gadget;
        struct device                   dev;
        struct list_head                list;
+       bool                            is_otg;
 };
 
 static struct class *udc_class;
@@ -403,10 +406,14 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
-       usb_gadget_disconnect(udc->gadget);
-       udc->driver->disconnect(udc->gadget);
+       /* If OTG, the otg core ensures UDC is stopped on unregister */
+       if (usb_otg_unregister_gadget(udc->gadget)) {
+               usb_gadget_disconnect(udc->gadget);
+               udc->driver->disconnect(udc->gadget);
+               usb_gadget_udc_stop(udc);
+       }
+
        udc->driver->unbind(udc->gadget);
-       usb_gadget_udc_stop(udc);
 
        udc->driver = NULL;
        udc->dev.driver = NULL;
@@ -466,12 +473,17 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct 
usb_gadget_driver *dri
        ret = driver->bind(udc->gadget, driver);
        if (ret)
                goto err1;
-       ret = usb_gadget_udc_start(udc);
-       if (ret) {
-               driver->unbind(udc->gadget);
-               goto err1;
+
+       /* If OTG, the otg core starts the UDC when needed */
+       udc->is_otg = !usb_otg_register_gadget(udc->gadget);
+       if (!udc->is_otg) {
+               ret = usb_gadget_udc_start(udc);
+               if (ret) {
+                       driver->unbind(udc->gadget);
+                       goto err1;
+               }
+               usb_gadget_connect(udc->gadget);
        }
-       usb_gadget_connect(udc->gadget);
 
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
        return 0;
@@ -583,6 +595,12 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
                return -EOPNOTSUPP;
        }
 
+       /* In OTG mode we don't support softconnect, but b_bus_req */
+       if (udc->is_otg) {
+               dev_err(dev, "soft-connect not supported in OTG mode\n");
+               return -EOPNOTSUPP;
+       }
+
        if (sysfs_streq(buf, "connect")) {
                usb_gadget_udc_start(udc);
                usb_gadget_connect(udc->gadget);
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to