]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blobdiff - drivers/usb/gadget/pxa2xx_udc.c
Merge branches 'release', 'ejd', 'sony' and 'wmi' into release
[mirror_ubuntu-kernels.git] / drivers / usb / gadget / pxa2xx_udc.c
index 1407ad1c81288bdfa1343e871bcd5be36d4622bf..096c41cc40d1bc8acd262fb75f5cf310d8189e6c 100644 (file)
@@ -24,7 +24,7 @@
  *
  */
 
-// #define     VERBOSE DBG_VERBOSE
+/* #define VERBOSE_DEBUG */
 
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
-#include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
@@ -54,7 +57,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>
 
@@ -100,6 +103,12 @@ static const char ep0name [] = "ep0";
 #error "Can't configure both IXP and PXA"
 #endif
 
+/* IXP doesn't yet support <linux/clk.h> */
+#define clk_get(dev,name)      NULL
+#define clk_enable(clk)                do { } while (0)
+#define clk_disable(clk)       do { } while (0)
+#define clk_put(clk)           do { } while (0)
+
 #endif
 
 #include "pxa2xx_udc.h"
@@ -125,8 +134,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;
@@ -675,7 +686,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
        /* kickstart this i/o queue? */
        if (list_empty(&ep->queue) && !ep->stopped) {
-               if (ep->desc == /* ep0 */) {
+               if (ep->desc == NULL/* ep0 */) {
                        unsigned        length = _req->length;
 
                        switch (dev->ep0state) {
@@ -729,7 +740,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        }
 
        /* pio or dma irq handler advances the queue. */
-       if (likely (req != 0))
+       if (likely(req != NULL))
                list_add_tail(&req->queue, &ep->queue);
        local_irq_restore(flags);
 
@@ -929,20 +940,31 @@ static void udc_disable(struct pxa2xx_udc *);
 /* We disable the UDC -- and its 48 MHz clock -- whenever it's not
  * in active use.
  */
-static int pullup(struct pxa2xx_udc *udc, int is_active)
+static int pullup(struct pxa2xx_udc *udc)
 {
-       is_active = is_active && udc->vbus && udc->pullup;
+       int is_active = udc->vbus && udc->pullup && !udc->suspended;
        DMSG("%s\n", is_active ? "active" : "inactive");
-       if (is_active)
-               udc_enable(udc);
-       else {
-               if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
-                       DMSG("disconnect %s\n", udc->driver
-                               ? udc->driver->driver.name
-                               : "(no driver)");
-                       stop_activity(udc, udc->driver);
+       if (is_active) {
+               if (!udc->active) {
+                       udc->active = 1;
+                       /* Enable clock for USB device */
+                       clk_enable(udc->clk);
+                       udc_enable(udc);
+               }
+       } else {
+               if (udc->active) {
+                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                               DMSG("disconnect %s\n", udc->driver
+                                       ? udc->driver->driver.name
+                                       : "(no driver)");
+                               stop_activity(udc, udc->driver);
+                       }
+                       udc_disable(udc);
+                       /* Disable clock for USB device */
+                       clk_disable(udc->clk);
+                       udc->active = 0;
                }
-               udc_disable(udc);
+
        }
        return 0;
 }
@@ -953,9 +975,9 @@ static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
        struct pxa2xx_udc       *udc;
 
        udc = container_of(_gadget, struct pxa2xx_udc, gadget);
-       udc->vbus = is_active = (is_active != 0);
+       udc->vbus = (is_active != 0);
        DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
-       pullup(udc, is_active);
+       pullup(udc);
        return 0;
 }
 
@@ -970,9 +992,8 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
        if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
                return -EOPNOTSUPP;
 
-       is_active = (is_active != 0);
-       udc->pullup = is_active;
-       pullup(udc, is_active);
+       udc->pullup = (is_active != 0);
+       pullup(udc);
        return 0;
 }
 
@@ -989,45 +1010,32 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = {
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static const char proc_node_name [] = "driver/udc";
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
 
 static int
-udc_proc_read(char *page, char **start, off_t off, int count,
-               int *eof, void *_dev)
+udc_seq_show(struct seq_file *m, void *_d)
 {
-       char                    *buf = page;
-       struct pxa2xx_udc       *dev = _dev;
-       char                    *next = buf;
-       unsigned                size = count;
+       struct pxa2xx_udc       *dev = m->private;
        unsigned long           flags;
-       int                     i, t;
+       int                     i;
        u32                     tmp;
 
-       if (off != 0)
-               return 0;
-
        local_irq_save(flags);
 
        /* basic device status */
-       t = scnprintf(next, size, DRIVER_DESC "\n"
+       seq_printf(m, DRIVER_DESC "\n"
                "%s version: %s\nGadget driver: %s\nHost %s\n\n",
                driver_name, DRIVER_VERSION SIZE_STR "(pio)",
                dev->driver ? dev->driver->driver.name : "(none)",
                is_vbus_present() ? "full speed" : "disconnected");
-       size -= t;
-       next += t;
 
        /* registers for device and ep0 */
-       t = scnprintf(next, size,
+       seq_printf(m,
                "uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
                UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
-       size -= t;
-       next += t;
 
        tmp = UDCCR;
-       t = scnprintf(next, size,
+       seq_printf(m,
                "udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
                (tmp & UDCCR_REM) ? " rem" : "",
                (tmp & UDCCR_RSTIR) ? " rstir" : "",
@@ -1037,11 +1045,9 @@ udc_proc_read(char *page, char **start, off_t off, int count,
                (tmp & UDCCR_RSM) ? " rsm" : "",
                (tmp & UDCCR_UDA) ? " uda" : "",
                (tmp & UDCCR_UDE) ? " ude" : "");
-       size -= t;
-       next += t;
 
        tmp = UDCCS0;
-       t = scnprintf(next, size,
+       seq_printf(m,
                "udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
                (tmp & UDCCS0_SA) ? " sa" : "",
                (tmp & UDCCS0_RNE) ? " rne" : "",
@@ -1051,28 +1057,22 @@ udc_proc_read(char *page, char **start, off_t off, int count,
                (tmp & UDCCS0_FTF) ? " ftf" : "",
                (tmp & UDCCS0_IPR) ? " ipr" : "",
                (tmp & UDCCS0_OPR) ? " opr" : "");
-       size -= t;
-       next += t;
 
        if (dev->has_cfr) {
                tmp = UDCCFR;
-               t = scnprintf(next, size,
+               seq_printf(m,
                        "udccfr %02X =%s%s\n", tmp,
                        (tmp & UDCCFR_AREN) ? " aren" : "",
                        (tmp & UDCCFR_ACM) ? " acm" : "");
-               size -= t;
-               next += t;
        }
 
        if (!is_vbus_present() || !dev->driver)
                goto done;
 
-       t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
+       seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
                dev->stats.write.bytes, dev->stats.write.ops,
                dev->stats.read.bytes, dev->stats.read.ops,
                dev->stats.irqs);
-       size -= t;
-       next += t;
 
        /* dump endpoint queues */
        for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@@ -1080,61 +1080,68 @@ udc_proc_read(char *page, char **start, off_t off, int count,
                struct pxa2xx_request   *req;
 
                if (i != 0) {
-                       const struct usb_endpoint_descriptor    *d;
+                       const struct usb_endpoint_descriptor    *desc;
 
-                       d = ep->desc;
-                       if (!d)
+                       desc = ep->desc;
+                       if (!desc)
                                continue;
                        tmp = *dev->ep [i].reg_udccs;
-                       t = scnprintf(next, size,
+                       seq_printf(m,
                                "%s max %d %s udccs %02x irqs %lu\n",
-                               ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
+                               ep->ep.name, le16_to_cpu(desc->wMaxPacketSize),
                                "pio", tmp, ep->pio_irqs);
                        /* TODO translate all five groups of udccs bits! */
 
                } else /* ep0 should only have one transfer queued */
-                       t = scnprintf(next, size, "ep0 max 16 pio irqs %lu\n",
+                       seq_printf(m, "ep0 max 16 pio irqs %lu\n",
                                ep->pio_irqs);
-               if (t <= 0 || t > size)
-                       goto done;
-               size -= t;
-               next += t;
 
                if (list_empty(&ep->queue)) {
-                       t = scnprintf(next, size, "\t(nothing queued)\n");
-                       if (t <= 0 || t > size)
-                               goto done;
-                       size -= t;
-                       next += t;
+                       seq_printf(m, "\t(nothing queued)\n");
                        continue;
                }
                list_for_each_entry(req, &ep->queue, queue) {
-                       t = scnprintf(next, size,
+                       seq_printf(m,
                                        "\treq %p len %d/%d buf %p\n",
                                        &req->req, req->req.actual,
                                        req->req.length, req->req.buf);
-                       if (t <= 0 || t > size)
-                               goto done;
-                       size -= t;
-                       next += t;
                }
        }
 
 done:
        local_irq_restore(flags);
-       *eof = 1;
-       return count - size;
+       return 0;
+}
+
+static int
+udc_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, udc_seq_show, inode->i_private);
 }
 
-#define create_proc_files() \
-       create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
-#define remove_proc_files() \
-       remove_proc_entry(proc_node_name, NULL)
+static const struct file_operations debug_fops = {
+       .open           = udc_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .owner          = THIS_MODULE,
+};
+
+#define create_debug_files(dev) \
+       do { \
+               dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
+                       S_IRUGO, NULL, dev, &debug_fops); \
+       } while (0)
+#define remove_debug_files(dev) \
+       do { \
+               if (dev->debugfs_udc) \
+                       debugfs_remove(dev->debugfs_udc); \
+       } while (0)
 
 #else  /* !CONFIG_USB_GADGET_DEBUG_FILES */
 
-#define create_proc_files() do {} while (0)
-#define remove_proc_files() do {} while (0)
+#define create_debug_files(dev) do {} while (0)
+#define remove_debug_files(dev) do {} while (0)
 
 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
@@ -1155,11 +1162,6 @@ static void udc_disable(struct pxa2xx_udc *dev)
 
        udc_clear_mask_UDCCR(UDCCR_UDE);
 
-#ifdef CONFIG_ARCH_PXA
-        /* Disable clock for USB device */
-       pxa_set_cken(CKEN_USB, 0);
-#endif
-
        ep0_idle (dev);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
 }
@@ -1200,12 +1202,6 @@ static void udc_enable (struct pxa2xx_udc *dev)
 {
        udc_clear_mask_UDCCR(UDCCR_UDE);
 
-#ifdef CONFIG_ARCH_PXA
-        /* Enable clock for USB device */
-       pxa_set_cken(CKEN_USB, 1);
-       udelay(5);
-#endif
-
        /* try to clear these bits before we enable the udc */
        udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR);
 
@@ -1296,7 +1292,7 @@ fail:
         * for set_configuration as well as eventual disconnect.
         */
        DMSG("registered gadget driver '%s'\n", driver->driver.name);
-       pullup(dev, 1);
+       pullup(dev);
        dump_state(dev);
        return 0;
 }
@@ -1339,11 +1335,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
                return -EINVAL;
 
        local_irq_disable();
-       pullup(dev, 0);
+       dev->pullup = 0;
+       pullup(dev);
        stop_activity(dev, driver);
        local_irq_enable();
 
        driver->unbind(&dev->gadget);
+       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
        device_del (&dev->gadget.dev);
@@ -1396,6 +1394,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;
 }
@@ -2098,7 +2099,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;
        }
 
@@ -2127,7 +2128,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;
@@ -2137,6 +2138,12 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        if (irq < 0)
                return -ENODEV;
 
+       dev->clk = clk_get(&pdev->dev, "UDCCLK");
+       if (IS_ERR(dev->clk)) {
+               retval = PTR_ERR(dev->clk);
+               goto err_clk;
+       }
+
        pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
                dev->has_cfr ? "" : " (!cfr)",
                SIZE_STR "(pio)"
@@ -2152,11 +2159,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;
 
@@ -2166,9 +2172,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);
        }
@@ -2193,13 +2197,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;
 
@@ -2210,22 +2210,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;
@@ -2234,22 +2229,35 @@ 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();
+       create_debug_files(dev);
 
        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:
+       clk_put(dev->clk);
+ err_clk:
+       return retval;
 }
 
 static void pxa2xx_udc_shutdown(struct platform_device *_dev)
@@ -2264,8 +2272,10 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
        if (dev->driver)
                return -EBUSY;
 
-       udc_disable(dev);
-       remove_proc_files();
+       dev->pullup = 0;
+       pullup(dev);
+
+       remove_debug_files(dev);
 
        if (dev->got_irq) {
                free_irq(platform_get_irq(pdev, 0), dev);
@@ -2284,6 +2294,8 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
        if (dev->mach->gpio_pullup)
                gpio_free(dev->mach->gpio_pullup);
 
+       clk_put(dev->clk);
+
        platform_set_drvdata(pdev, NULL);
        the_controller = NULL;
        return 0;
@@ -2308,10 +2320,15 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
 static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
 {
        struct pxa2xx_udc       *udc = platform_get_drvdata(dev);
+       unsigned long flags;
 
        if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
                WARN("USB host won't detect disconnect!\n");
-       pullup(udc, 0);
+       udc->suspended = 1;
+
+       local_irq_save(flags);
+       pullup(udc);
+       local_irq_restore(flags);
 
        return 0;
 }
@@ -2319,8 +2336,12 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state)
 static int pxa2xx_udc_resume(struct platform_device *dev)
 {
        struct pxa2xx_udc       *udc = platform_get_drvdata(dev);
+       unsigned long flags;
 
-       pullup(udc, 1);
+       udc->suspended = 0;
+       local_irq_save(flags);
+       pullup(udc);
+       local_irq_restore(flags);
 
        return 0;
 }
@@ -2345,7 +2366,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);