s3c-hsudc: Add basic otg transceiver handling
authorHeiko Stübner <heiko@sntech.de>
Sun, 21 Aug 2011 12:32:14 +0000 (14:32 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 22 Aug 2011 23:03:15 +0000 (16:03 -0700)
Makes it possible to use i.e. gpio-vbus to handle vbus events.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/s3c-hsudc.c

index 00056c2..3e96cc5 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/clk.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 #include <linux/prefetch.h>
 
 #include <mach/regs-s3c2443-clock.h>
@@ -137,6 +138,7 @@ struct s3c_hsudc {
        struct usb_gadget_driver *driver;
        struct device *dev;
        struct s3c24xx_hsudc_platdata *pd;
+       struct otg_transceiver *transceiver;
        spinlock_t lock;
        void __iomem *regs;
        struct resource *mem_rsrc;
@@ -1171,6 +1173,22 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver,
                return ret;
        }
 
+       /* connect to bus through transceiver */
+       if (hsudc->transceiver) {
+               ret = otg_set_peripheral(hsudc->transceiver, &hsudc->gadget);
+               if (ret) {
+                       dev_err(hsudc->dev, "%s: can't bind to transceiver\n",
+                                       hsudc->gadget.name);
+                       driver->unbind(&hsudc->gadget);
+
+                       device_del(&hsudc->gadget.dev);
+
+                       hsudc->driver = NULL;
+                       hsudc->gadget.dev.driver = NULL;
+                       return ret;
+               }
+       }
+
        enable_irq(hsudc->irq);
        dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name);
 
@@ -1201,6 +1219,9 @@ static int s3c_hsudc_stop(struct usb_gadget_driver *driver)
        s3c_hsudc_stop_activity(hsudc, driver);
        spin_unlock_irqrestore(&hsudc->lock, flags);
 
+       if (hsudc->transceiver)
+               (void) otg_set_peripheral(hsudc->transceiver, NULL);
+
        driver->unbind(&hsudc->gadget);
        device_del(&hsudc->gadget.dev);
        disable_irq(hsudc->irq);
@@ -1247,6 +1268,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
        hsudc->dev = dev;
        hsudc->pd = pdev->dev.platform_data;
 
+       hsudc->transceiver = otg_get_transceiver();
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "unable to obtain driver resource data\n");