Adapt the dwc3 gadget to use drd library functions.
In prepration to support DRD on dwc3.

Signed-off-by: George Cherian <george.cher...@ti.com>
---
 drivers/usb/dwc3/gadget.c | 128 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 100 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 2c54d45..a75fae5 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -29,6 +29,7 @@
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/drd.h>
 
 #include "debug.h"
 #include "core.h"
@@ -2681,6 +2682,89 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
        return ret;
 }
 
+void dwc3_gadget_release(struct device *dev)
+{
+       struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev);
+       struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(gadget);
+       struct dwc3 *dwc = dwc_gadget->dwc;
+
+       dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
+       dwc3_gadget_free_endpoints(dwc);
+       dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
+                         dwc->ep0_bounce, dwc->ep0_bounce_addr);
+       kfree(dwc->setup_buf);
+       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+                         dwc->ep0_trb, dwc->ep0_trb_addr);
+       dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
+                         dwc->ctrl_req, dwc->ctrl_req_addr);
+       usb_drd_unregister_udc(dwc->dev);
+       kfree(dwc_gadget);
+}
+
+int dwc3_gadget_setup(void *data)
+{
+       struct dwc3 *dwc = data;
+       struct dwc3_gadget *dwc_gadget;
+       struct usb_drd_gadget *drd_gadget;
+       struct usb_drd_setup *gadget_setup;
+       int ret;
+
+       drd_gadget = kzalloc(sizeof(*drd_gadget), GFP_KERNEL);
+       if (!drd_gadget) {
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       gadget_setup = kzalloc(sizeof(*gadget_setup), GFP_KERNEL);
+       if (!gadget_setup) {
+               ret = -ENOMEM;
+               goto err2;
+       }
+
+       dwc_gadget = kzalloc(sizeof(*dwc_gadget), GFP_KERNEL);
+       if (!dwc_gadget) {
+               ret = -ENOMEM;
+               goto err3;
+       }
+
+       drd_gadget->g_driver = dwc->gadget_driver;
+
+       /*
+        * Pass the DWC3 specific routines for
+        * switching roles to the drd library
+        */
+       gadget_setup->ll_start = NULL;
+       gadget_setup->ll_stop = NULL;
+       gadget_setup->ll_release = dwc3_gadget_release;
+       gadget_setup->data =  (void *)dwc;
+       drd_gadget->gadget_setup = gadget_setup;
+
+       dwc_gadget->gadget.ops                  = &dwc3_gadget_ops;
+       dwc_gadget->gadget.max_speed            = USB_SPEED_SUPER;
+       dwc_gadget->gadget.speed                = USB_SPEED_UNKNOWN;
+       dwc_gadget->gadget.sg_supported         = true;
+       dwc_gadget->gadget.name                 = "dwc3-gadget";
+       dwc_gadget->dwc                         = dwc;
+       drd_gadget->gadget = &dwc_gadget->gadget;
+
+       /*
+        * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
+        * on ep out.
+        */
+       dwc_gadget->gadget.quirk_ep_out_aligned_size = true;
+       dwc->dwc_gadget = dwc_gadget;
+       usb_drd_register_udc(dwc->dev, drd_gadget);
+
+       return 0;
+
+err3:
+       kfree(gadget_setup);
+err2:
+       kfree(drd_gadget);
+err1:
+       return ret;
+}
+
 /**
  * dwc3_gadget_init - Initializes gadget related registers
  * @dwc: pointer to our controller context structure
@@ -2690,7 +2774,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 int dwc3_gadget_init(struct dwc3 *dwc)
 {
        int                                     ret;
-       struct dwc3_gadget                      *dwc_gadget;
 
        dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
                        &dwc->ctrl_req_addr, GFP_KERNEL);
@@ -2723,24 +2806,9 @@ int dwc3_gadget_init(struct dwc3 *dwc)
                goto err3;
        }
 
-       dwc_gadget = kzalloc(sizeof(*dwc_gadget), GFP_KERNEL);
-       if (!dwc_gadget) {
-               ret = -ENOMEM;
+       ret = dwc3_gadget_setup(dwc);
+       if (ret)
                goto err3;
-       }
-
-       dwc_gadget->gadget.ops                  = &dwc3_gadget_ops;
-       dwc_gadget->gadget.max_speed            = USB_SPEED_SUPER;
-       dwc_gadget->gadget.speed                = USB_SPEED_UNKNOWN;
-       dwc_gadget->gadget.sg_supported = true;
-       dwc_gadget->gadget.name         = "dwc3-gadget";
-       dwc_gadget->dwc = dwc;
-
-       /*
-        * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
-        * on ep out.
-        */
-       dwc_gadget->gadget.quirk_ep_out_aligned_size = true;
 
        /*
         * REVISIT: Here we should clear all pending IRQs to be
@@ -2751,7 +2819,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        if (ret)
                goto err4;
 
-       ret = usb_add_gadget_udc(dwc->dev, &dwc_gadget->gadget);
+       ret = usb_add_gadget_udc_release(dwc->dev, &dwc->dwc_gadget->gadget,
+                                        dwc3_gadget_release);
        if (ret) {
                dev_err(dwc->dev, "failed to register udc\n");
                goto err4;
@@ -2760,6 +2829,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        return 0;
 
 err4:
+       usb_drd_unregister_udc(dwc->dev);
        dwc3_gadget_free_endpoints(dwc);
        dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
                        dwc->ep0_bounce, dwc->ep0_bounce_addr);
@@ -2785,20 +2855,22 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 {
        struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget;
 
-       usb_del_gadget_udc(&dwc_gadget->gadget);
+       if (usb_drd_get_state(dwc->dev) & DRD_DEVICE_REGISTERED) {
+               usb_del_gadget_udc(&dwc_gadget->gadget);
 
-       dwc3_gadget_free_endpoints(dwc);
+               dwc3_gadget_free_endpoints(dwc);
 
-       dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
-                       dwc->ep0_bounce, dwc->ep0_bounce_addr);
+               dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
+                                 dwc->ep0_bounce, dwc->ep0_bounce_addr);
 
-       kfree(dwc->setup_buf);
+               kfree(dwc->setup_buf);
 
-       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
-                       dwc->ep0_trb, dwc->ep0_trb_addr);
+               dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+                                 dwc->ep0_trb, dwc->ep0_trb_addr);
 
-       dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
-                       dwc->ctrl_req, dwc->ctrl_req_addr);
+               dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
+                                 dwc->ctrl_req, dwc->ctrl_req_addr);
+       }
 }
 
 int dwc3_gadget_suspend(struct dwc3 *dwc)
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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