ARM: 5965/1: Fix soft lockup in at91 udc driver
[safe/jmp/linux-2.6] / drivers / usb / gadget / at91_udc.c
index fd15ced..df1bae9 100644 (file)
 #include <linux/usb/gadget.h>
 
 #include <asm/byteorder.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/mach-types.h>
 #include <asm/gpio.h>
 
-#include <asm/arch/board.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/at91sam9261_matrix.h>
+#include <mach/board.h>
+#include <mach/cpu.h>
+#include <mach/at91sam9261_matrix.h>
 
 #include "at91_udc.h"
 
@@ -231,6 +230,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_ops = {
+       .owner          = THIS_MODULE,
        .open           = proc_udc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -239,15 +239,7 @@ static const struct file_operations proc_ops = {
 
 static void create_debug_file(struct at91_udc *udc)
 {
-       struct proc_dir_entry *pde;
-
-       pde = create_proc_entry (debug_filename, 0, NULL);
-       udc->pde = pde;
-       if (pde == NULL)
-               return;
-
-       pde->proc_fops = &proc_ops;
-       pde->data = udc;
+       udc->pde = proc_create_data(debug_filename, 0, NULL, &proc_ops, udc);
 }
 
 static void remove_debug_file(struct at91_udc *udc)
@@ -389,6 +381,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
        u32             csr = __raw_readl(creg);
        u8 __iomem      *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
        unsigned        total, count, is_last;
+       u8              *buf;
 
        /*
         * TODO: allow for writing two packets to the fifo ... that'll
@@ -413,6 +406,8 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
                        return 0;
        }
 
+       buf = req->req.buf + req->req.actual;
+       prefetch(buf);
        total = req->req.length - req->req.actual;
        if (ep->ep.maxpacket < total) {
                count = ep->ep.maxpacket;
@@ -435,7 +430,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
         * recover when the actual bytecount matters (e.g. for USB Test
         * and Measurement Class devices).
         */
-       __raw_writesb(dreg, req->req.buf + req->req.actual, count);
+       __raw_writesb(dreg, buf, count);
        csr &= ~SET_FX;
        csr |= CLR_FX | AT91_UDP_TXPKTRDY;
        __raw_writel(csr, creg);
@@ -457,7 +452,7 @@ static void nuke(struct at91_ep *ep, int status)
        if (list_empty(&ep->queue))
                return;
 
-       VDBG("%s %s\n", __FUNCTION__, ep->ep.name);
+       VDBG("%s %s\n", __func__, ep->ep.name);
        while (!list_empty(&ep->queue)) {
                req = list_entry(ep->queue.next, struct at91_request, queue);
                done(ep, req, status);
@@ -490,7 +485,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
                return -ESHUTDOWN;
        }
 
-       tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+       tmp = usb_endpoint_type(desc);
        switch (tmp) {
        case USB_ENDPOINT_XFER_CONTROL:
                DBG("only one control endpoint\n");
@@ -522,7 +517,7 @@ ok:
        local_irq_save(flags);
 
        /* initialize endpoint to match this descriptor */
-       ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
+       ep->is_in = usb_endpoint_dir_in(desc);
        ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
        ep->stopped = 0;
        if (ep->is_in)
@@ -792,7 +787,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
        int             status = -EINVAL;
        unsigned long   flags;
 
-       DBG("%s\n", __FUNCTION__ );
+       DBG("%s\n", __func__ );
        local_irq_save(flags);
 
        if (!udc->clocked || !udc->suspended)
@@ -892,12 +887,12 @@ static void pullup(struct at91_udc *udc, int is_on)
                at91_udp_write(udc, AT91_UDP_TXVC, 0);
                if (cpu_is_at91rm9200())
                        gpio_set_value(udc->board.pullup_pin, active);
-               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
+               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
                        u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
                        txvc |= AT91_UDP_TXVC_PUON;
                        at91_udp_write(udc, AT91_UDP_TXVC, txvc);
-               } else if (cpu_is_at91sam9261()) {
+               } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
                        u32     usbpucr;
 
                        usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
@@ -910,12 +905,12 @@ static void pullup(struct at91_udc *udc, int is_on)
                at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
                if (cpu_is_at91rm9200())
                        gpio_set_value(udc->board.pullup_pin, !active);
-               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
+               else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
                        u32     txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
                        txvc &= ~AT91_UDP_TXVC_PUON;
                        at91_udp_write(udc, AT91_UDP_TXVC, txvc);
-               } else if (cpu_is_at91sam9261()) {
+               } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
                        u32     usbpucr;
 
                        usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
@@ -1375,6 +1370,12 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
 {
        struct at91_udc         *udc = _udc;
        u32                     rescans = 5;
+       int                     disable_clock = 0;
+
+       if (!udc->clocked) {
+               clk_on(udc);
+               disable_clock = 1;
+       }
 
        while (rescans--) {
                u32 status;
@@ -1463,6 +1464,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
                }
        }
 
+       if (disable_clock)
+               clk_off(udc);
+
        return IRQ_HANDLED;
 }
 
@@ -1479,7 +1483,7 @@ static struct at91_udc controller = {
                .ep0    = &controller.ep[0].ep,
                .name   = driver_name,
                .dev    = {
-                       .bus_id = "gadget",
+                       .init_name = "gadget",
                        .release = nop_release,
                }
        },
@@ -1579,7 +1583,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
 
        udc->driver = driver;
        udc->gadget.dev.driver = &driver->driver;
-       udc->gadget.dev.driver_data = &driver->driver;
+       dev_set_drvdata(&udc->gadget.dev, &driver->driver);
        udc->enabled = 1;
        udc->selfpowered = 1;
 
@@ -1588,7 +1592,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
                DBG("driver->bind() returned %d\n", retval);
                udc->driver = NULL;
                udc->gadget.dev.driver = NULL;
-               udc->gadget.dev.driver_data = NULL;
+               dev_set_drvdata(&udc->gadget.dev, NULL);
                udc->enabled = 0;
                udc->selfpowered = 0;
                return retval;
@@ -1618,7 +1622,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 
        driver->unbind(&udc->gadget);
        udc->gadget.dev.driver = NULL;
-       udc->gadget.dev.driver_data = NULL;
+       dev_set_drvdata(&udc->gadget.dev, NULL);
        udc->driver = NULL;
 
        DBG("unbound from %s\n", driver->driver.name);
@@ -1661,9 +1665,7 @@ static int __init at91udc_probe(struct platform_device *pdev)
        if (!res)
                return -ENXIO;
 
-       if (!request_mem_region(res->start,
-                       res->end - res->start + 1,
-                       driver_name)) {
+       if (!request_mem_region(res->start, resource_size(res), driver_name)) {
                DBG("someone's using UDC memory\n");
                return -EBUSY;
        }
@@ -1691,7 +1693,20 @@ static int __init at91udc_probe(struct platform_device *pdev)
                                udc->board.pullup_active_low);
        }
 
-       udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
+       /* newer chips have more FIFO memory than rm9200 */
+       if (cpu_is_at91sam9260()) {
+               udc->ep[0].maxpacket = 64;
+               udc->ep[3].maxpacket = 64;
+               udc->ep[4].maxpacket = 512;
+               udc->ep[5].maxpacket = 512;
+       } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
+               udc->ep[3].maxpacket = 64;
+       } else if (cpu_is_at91sam9263()) {
+               udc->ep[0].maxpacket = 64;
+               udc->ep[3].maxpacket = 64;
+       }
+
+       udc->udp_baseaddr = ioremap(res->start, resource_size(res));
        if (!udc->udp_baseaddr) {
                retval = -ENOMEM;
                goto fail0a;
@@ -1746,7 +1761,6 @@ static int __init at91udc_probe(struct platform_device *pdev)
                                IRQF_DISABLED, driver_name, udc)) {
                        DBG("request vbus irq %d failed\n",
                                        udc->board.vbus_pin);
-                       free_irq(udc->udp_irq, udc);
                        retval = -EBUSY;
                        goto fail3;
                }
@@ -1774,7 +1788,7 @@ fail0a:
        if (cpu_is_at91rm9200())
                gpio_free(udc->board.pullup_pin);
 fail0:
-       release_mem_region(res->start, res->end - res->start + 1);
+       release_mem_region(res->start, resource_size(res));
        DBG("%s probe failed, %d\n", driver_name, retval);
        return retval;
 }
@@ -1806,7 +1820,7 @@ static int __exit at91udc_remove(struct platform_device *pdev)
                gpio_free(udc->board.pullup_pin);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, res->end - res->start + 1);
+       release_mem_region(res->start, resource_size(res));
 
        clk_put(udc->iclk);
        clk_put(udc->fclk);