USB: gadget: pxa2xx_udc supports inverted vbus
[safe/jmp/linux-2.6] / drivers / usb / gadget / pxa2xx_udc.c
index 484de6e..8bd9ce2 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
@@ -54,7 +56,7 @@
 #include <asm/hardware.h>
 
 #include <linux/usb/ch9.h>
-#include <linux/usb_gadget.h>
+#include <linux/usb/gadget.h>
 
 #include <asm/mach/udc_pxa2xx.h>
 
@@ -93,8 +95,6 @@ static const char driver_name [] = "pxa2xx_udc";
 static const char ep0name [] = "ep0";
 
 
-// #define     DISABLE_TEST_MODE
-
 #ifdef CONFIG_ARCH_IXP4XX
 
 /* cpu-specific register addresses are compiled in to this code */
@@ -113,17 +113,6 @@ static const char ep0name [] = "ep0";
 #define SIZE_STR       ""
 #endif
 
-#ifdef DISABLE_TEST_MODE
-/* (mode == 0) == no undocumented chip tweaks
- * (mode & 1)  == double buffer bulk IN
- * (mode & 2)  == double buffer bulk OUT
- * ... so mode = 3 (or 7, 15, etc) does it for both
- */
-static ushort fifo_mode = 0;
-module_param(fifo_mode, ushort, 0);
-MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode");
-#endif
-
 /* ---------------------------------------------------------------------------
  *     endpoint related parts of the api to the usb controller hardware,
  *     used by gadget driver; and the inner talker-to-hardware core.
@@ -138,8 +127,10 @@ static int is_vbus_present(void)
 {
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
-       if (mach->gpio_vbus)
-               return gpio_get_value(mach->gpio_vbus);
+       if (mach->gpio_vbus) {
+               int value = gpio_get_value(mach->gpio_vbus);
+               return mach->gpio_vbus_inverted ? !value : value;
+       }
        if (mach->udc_is_connected)
                return mach->udc_is_connected();
        return 1;
@@ -341,26 +332,6 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
        kfree(req);
 }
 
-
-static void *
-pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-       dma_addr_t *dma, gfp_t gfp_flags)
-{
-       char                    *retval;
-
-       retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
-       if (retval)
-               *dma = (dma_addr_t)~0;
-       return retval;
-}
-
-static void
-pxa2xx_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma,
-               unsigned bytes)
-{
-       kfree (buf);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -927,9 +898,6 @@ static struct usb_ep_ops pxa2xx_ep_ops = {
        .alloc_request  = pxa2xx_ep_alloc_request,
        .free_request   = pxa2xx_ep_free_request,
 
-       .alloc_buffer   = pxa2xx_ep_alloc_buffer,
-       .free_buffer    = pxa2xx_ep_free_buffer,
-
        .queue          = pxa2xx_ep_queue,
        .dequeue        = pxa2xx_ep_dequeue,
 
@@ -1003,7 +971,7 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
        udc = container_of(_gadget, struct pxa2xx_udc, gadget);
 
        /* not all boards support pullup control */
-       if (!udc->mach->udc_command)
+       if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
                return -EOPNOTSUPP;
 
        is_active = (is_active != 0);
@@ -1193,7 +1161,7 @@ static void udc_disable(struct pxa2xx_udc *dev)
 
 #ifdef CONFIG_ARCH_PXA
         /* Disable clock for USB device */
-       pxa_set_cken(CKEN_USB, 0);
+       clk_disable(dev->clk);
 #endif
 
        ep0_idle (dev);
@@ -1238,8 +1206,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
 
 #ifdef CONFIG_ARCH_PXA
         /* Enable clock for USB device */
-       pxa_set_cken(CKEN_USB, 1);
-       udelay(5);
+       clk_enable(dev->clk);
 #endif
 
        /* try to clear these bits before we enable the udc */
@@ -1275,23 +1242,6 @@ static void udc_enable (struct pxa2xx_udc *dev)
                UDC_RES2 = 0x00;
        }
 
-#ifdef DISABLE_TEST_MODE
-       /* "test mode" seems to have become the default in later chip
-        * revs, preventing double buffering (and invalidating docs).
-        * this EXPERIMENT enables it for bulk endpoints by tweaking
-        * undefined/reserved register bits (that other drivers clear).
-        * Belcarra code comments noted this usage.
-        */
-       if (fifo_mode & 1) {    /* IN endpoints */
-               UDC_RES1 |= USIR0_IR1|USIR0_IR6;
-               UDC_RES2 |= USIR1_IR11;
-       }
-       if (fifo_mode & 2) {    /* OUT endpoints */
-               UDC_RES1 |= USIR0_IR2|USIR0_IR7;
-               UDC_RES2 |= USIR1_IR12;
-       }
-#endif
-
        /* enable suspend/resume and reset irqs */
        udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
 
@@ -1397,6 +1347,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
        local_irq_enable();
 
        driver->unbind(&dev->gadget);
+       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
        device_del (&dev->gadget.dev);
@@ -1449,6 +1400,9 @@ static irqreturn_t udc_vbus_irq(int irq, void *_dev)
        struct pxa2xx_udc       *dev = _dev;
        int                     vbus = gpio_get_value(dev->mach->gpio_vbus);
 
+       if (dev->mach->gpio_vbus_inverted)
+               vbus = !vbus;
+
        pxa2xx_udc_vbus_session(&dev->gadget, vbus);
        return IRQ_HANDLED;
 }
@@ -2151,7 +2105,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        /* insist on Intel/ARM/XScale */
        asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
        if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
-               printk(KERN_ERR "%s: not XScale!\n", driver_name);
+               pr_err("%s: not XScale!\n", driver_name);
                return -ENODEV;
        }
 
@@ -2180,7 +2134,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
                break;
 #endif
        default:
-               printk(KERN_ERR "%s: unrecognized processor: %08x\n",
+               pr_err("%s: unrecognized processor: %08x\n",
                        driver_name, chiprev);
                /* iop3xx, ixp4xx, ... */
                return -ENODEV;
@@ -2190,6 +2144,14 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        if (irq < 0)
                return -ENODEV;
 
+#ifdef CONFIG_ARCH_PXA
+       dev->clk = clk_get(&pdev->dev, "UDCCLK");
+       if (IS_ERR(dev->clk)) {
+               retval = PTR_ERR(dev->clk);
+               goto err_clk;
+       }
+#endif
+
        pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
                dev->has_cfr ? "" : " (!cfr)",
                SIZE_STR "(pio)"
@@ -2205,11 +2167,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
                        dev_dbg(&pdev->dev,
                                "can't get vbus gpio %d, err: %d\n",
                                dev->mach->gpio_vbus, retval);
-                       return -EBUSY;
+                       goto err_gpio_vbus;
                }
                gpio_direction_input(dev->mach->gpio_vbus);
                vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
-               set_irq_type(vbus_irq, IRQT_BOTHEDGE);
        } else
                vbus_irq = 0;
 
@@ -2219,9 +2180,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
                        dev_dbg(&pdev->dev,
                                "can't get pullup gpio %d, err: %d\n",
                                dev->mach->gpio_pullup, retval);
-                       if (dev->mach->gpio_vbus)
-                               gpio_free(dev->mach->gpio_vbus);
-                       return -EBUSY;
+                       goto err_gpio_pullup;
                }
                gpio_direction_output(dev->mach->gpio_pullup, 0);
        }
@@ -2246,13 +2205,9 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        retval = request_irq(irq, pxa2xx_udc_irq,
                        IRQF_DISABLED, driver_name, dev);
        if (retval != 0) {
-               printk(KERN_ERR "%s: can't get irq %d, err %d\n",
+               pr_err("%s: can't get irq %d, err %d\n",
                        driver_name, irq, retval);
-               if (dev->mach->gpio_pullup)
-                       gpio_free(dev->mach->gpio_pullup);
-               if (dev->mach->gpio_vbus)
-                       gpio_free(dev->mach->gpio_vbus);
-               return -EBUSY;
+               goto err_irq1;
        }
        dev->got_irq = 1;
 
@@ -2263,22 +2218,17 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
                                IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
                                driver_name, dev);
                if (retval != 0) {
-                       printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+                       pr_err("%s: can't get irq %i, err %d\n",
                                driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 lubbock_fail0:
-                       free_irq(irq, dev);
-                       if (dev->mach->gpio_pullup)
-                               gpio_free(dev->mach->gpio_pullup);
-                       if (dev->mach->gpio_vbus)
-                               gpio_free(dev->mach->gpio_vbus);
-                       return -EBUSY;
+                       goto err_irq_lub;
                }
                retval = request_irq(LUBBOCK_USB_IRQ,
                                lubbock_vbus_irq,
                                IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
                                driver_name, dev);
                if (retval != 0) {
-                       printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+                       pr_err("%s: can't get irq %i, err %d\n",
                                driver_name, LUBBOCK_USB_IRQ, retval);
                        free_irq(LUBBOCK_USB_DISC_IRQ, dev);
                        goto lubbock_fail0;
@@ -2287,22 +2237,37 @@ lubbock_fail0:
 #endif
        if (vbus_irq) {
                retval = request_irq(vbus_irq, udc_vbus_irq,
-                               IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+                               IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                                driver_name, dev);
                if (retval != 0) {
-                       printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+                       pr_err("%s: can't get irq %i, err %d\n",
                                driver_name, vbus_irq, retval);
-                       free_irq(irq, dev);
-                       if (dev->mach->gpio_pullup)
-                               gpio_free(dev->mach->gpio_pullup);
-                       if (dev->mach->gpio_vbus)
-                               gpio_free(dev->mach->gpio_vbus);
-                       return -EBUSY;
+                       goto err_vbus_irq;
                }
        }
        create_proc_files();
 
        return 0;
+
+ err_vbus_irq:
+#ifdef CONFIG_ARCH_LUBBOCK
+       free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+ err_irq_lub:
+#endif
+       free_irq(irq, dev);
+ err_irq1:
+       if (dev->mach->gpio_pullup)
+               gpio_free(dev->mach->gpio_pullup);
+ err_gpio_pullup:
+       if (dev->mach->gpio_vbus)
+               gpio_free(dev->mach->gpio_vbus);
+ err_gpio_vbus:
+#ifdef CONFIG_ARCH_PXA
+       clk_put(dev->clk);
+ err_clk:
+#endif
+       return retval;
 }
 
 static void pxa2xx_udc_shutdown(struct platform_device *_dev)
@@ -2337,6 +2302,10 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
        if (dev->mach->gpio_pullup)
                gpio_free(dev->mach->gpio_pullup);
 
+#ifdef CONFIG_ARCH_PXA
+       clk_put(dev->clk);
+#endif
+
        platform_set_drvdata(pdev, NULL);
        the_controller = NULL;
        return 0;
@@ -2362,7 +2331,7 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
 {
        struct pxa2xx_udc       *udc = platform_get_drvdata(dev);
 
-       if (!udc->mach->udc_command)
+       if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
                WARN("USB host won't detect disconnect!\n");
        pullup(udc, 0);
 
@@ -2398,7 +2367,7 @@ static struct platform_driver udc_driver = {
 
 static int __init udc_init(void)
 {
-       printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
+       pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
        return platform_driver_probe(&udc_driver, pxa2xx_udc_probe);
 }
 module_init(udc_init);