]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
musb_hdrc: Various bugfixes and other updates
authorDavid Brownell <dbrownell@users.sourceforge.net>
Fri, 27 Oct 2006 12:52:38 +0000 (15:52 +0300)
committerTony Lindgren <tony@atomide.com>
Fri, 27 Oct 2006 12:52:38 +0000 (15:52 +0300)
Various bugfixes:
    - gadget side does dma_sync_single_for_*() if the buffer
      was mapped by the gadget driver (none do that just yet)
    - host side rx, always force dma request off "just in case",
      instead of just for Mentor's DMA (i.e. not just OMAP2430)
    - complain louder about the board needing different driver config
    - iounmap() registers on rmmod
    - fault handling fixes in tusb_start()
    - (from TI) save dma mask so modprobe after use_dma=n can use dma
    - (from TI) gadget side zero-length IN likes TXPKTRDY before status stage

Other updates:
    - catch up to pt_regs finally leaving the irq path, other build fixes
    - remove pointless headers like <linux/pci.h>
    - RemoveMoreCamelCaseNastiness
    - resolve some config-specific compiler warning/error messages
    - dump tusb irq status register too
    - remove that MIN_DMA thing; dma logic must now handle zlps
      in all cases, not just to terminate a transfer
    - comment fixes

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
drivers/usb/musb/davinci.c
drivers/usb/musb/g_ep0.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_gadget.h
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_procfs.c
drivers/usb/musb/musbdefs.h
drivers/usb/musb/omap2430.c
drivers/usb/musb/plat_uds.c
drivers/usb/musb/tusb6010.c

index 76d6849c8ccd950ba92b27acc490cd29bd0297d2..8890f21c30ffa868877e06b25c6176b5c1f6c848 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -246,7 +245,7 @@ static void davinci_set_vbus(struct musb *musb, int is_on)
        return davinci_vbus_power(musb, is_on, 0);
 }
 
-static irqreturn_t davinci_interrupt(int irq, void *__hci, struct pt_regs *r)
+static irqreturn_t davinci_interrupt(int irq, void *__hci)
 {
        unsigned long   flags;
        irqreturn_t     retval = IRQ_NONE;
@@ -289,7 +288,6 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci, struct pt_regs *r)
                        >> DAVINCI_USB_TXINT_SHIFT;
        musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK)
                        >> DAVINCI_USB_USBINT_SHIFT;
-       musb->int_regs = r;
 
        /* treat DRVVBUS irq like an ID change IRQ (for now) */
        if (tmp & (1 << (8 + DAVINCI_USB_USBINT_SHIFT))) {
@@ -317,7 +315,6 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci, struct pt_regs *r)
        /* irq stays asserted until EOI is written */
        musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);
 
-       musb->int_regs = NULL;
        spin_unlock_irqrestore(&musb->Lock, flags);
 
        /* REVISIT we sometimes get unhandled IRQs
index fc6a7c0bf10c0e01aafd5eeeb709e79b28c75526..b38a86830376afa5ab166484c11a107e5edf825c 100644 (file)
@@ -556,9 +556,11 @@ musb_read_setup(struct musb *pThis, struct usb_ctrlrequest *req)
         */
        pThis->bSetAddress = FALSE;
        pThis->ackpend = MGC_M_CSR0_P_SVDRXPKTRDY;
-       if (req->wLength == 0)
+       if (req->wLength == 0) {
+               if (req->bRequestType & USB_DIR_IN)
+                       pThis->ackpend |= MGC_M_CSR0_TXPKTRDY;
                pThis->ep0_state = MGC_END0_STAGE_ACKWAIT;
-       else if (req->bRequestType & USB_DIR_IN) {
+       else if (req->bRequestType & USB_DIR_IN) {
                pThis->ep0_state = MGC_END0_STAGE_TX;
                musb_writew(regs, MGC_O_HDRC_CSR0, MGC_M_CSR0_P_SVDRXPKTRDY);
                while ((musb_readw(regs, MGC_O_HDRC_CSR0)
index c701f0b96f297907721cc7cb54f65b043fee9dd9..9456608d5ca38ff5453d3edefd3f0889cf20edb0 100644 (file)
@@ -118,15 +118,23 @@ __acquires(ep->musb->Lock)
 
        ep->busy = 1;
        spin_unlock(&musb->Lock);
-       if (is_dma_capable() && req->mapped) {
-               dma_unmap_single(musb->controller,
-                               req->request.dma,
-                               req->request.length,
-                               req->bTx
-                                       ? DMA_TO_DEVICE
-                                       : DMA_FROM_DEVICE);
-               req->request.dma = DMA_ADDR_INVALID;
-               req->mapped = 0;
+       if (is_dma_capable()) {
+               if (req->mapped) {
+                       dma_unmap_single(musb->controller,
+                                       req->request.dma,
+                                       req->request.length,
+                                       req->bTx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
+                       req->request.dma = DMA_ADDR_INVALID;
+                       req->mapped = 0;
+               } else
+                       dma_sync_single_for_cpu(musb->controller,
+                                       req->request.dma,
+                                       req->request.length,
+                                       req->bTx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
        }
        if (pRequest->status == 0)
                DBG(5, "%s done request %p,  %d/%d\n",
@@ -1135,7 +1143,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 {
        struct musb_ep          *pEnd;
        struct musb_request     *pRequest;
-       struct musb             *pThis;
+       struct musb             *musb;
        int                     status = 0;
        unsigned long           lockflags;
 
@@ -1143,10 +1151,10 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
                return -EINVAL;
 
        pEnd = to_musb_ep(ep);
-       pThis = pEnd->pThis;
+       musb = pEnd->pThis;
 
        pRequest = to_musb_request(req);
-       pRequest->musb = pThis;
+       pRequest->musb = musb;
 
        if (pRequest->ep != pEnd)
                return -EINVAL;
@@ -1159,23 +1167,31 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
        pRequest->bEnd = pEnd->bEndNumber;
        pRequest->bTx = pEnd->is_in;
 
-       if (is_dma_capable()
-                       && pRequest->request.dma == DMA_ADDR_INVALID
-                       && pRequest->request.length >= MIN_DMA_REQUEST
-                       && pEnd->dma) {
-               pRequest->request.dma = dma_map_single(pThis->controller,
-                               pRequest->request.buf,
-                               pRequest->request.length,
-                               pRequest->bTx
-                                       ? DMA_TO_DEVICE
-                                       : DMA_FROM_DEVICE);
-               pRequest->mapped = 1;
+       if (is_dma_capable() && pEnd->dma) {
+               if (pRequest->request.dma == DMA_ADDR_INVALID) {
+                       pRequest->request.dma = dma_map_single(
+                                       musb->controller,
+                                       pRequest->request.buf,
+                                       pRequest->request.length,
+                                       pRequest->bTx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
+                       pRequest->mapped = 1;
+               } else {
+                       dma_sync_single_for_device(musb->controller,
+                                       pRequest->request.dma,
+                                       pRequest->request.length,
+                                       pRequest->bTx
+                                               ? DMA_TO_DEVICE
+                                               : DMA_FROM_DEVICE);
+                       pRequest->mapped = 0;
+               }
        } else if (!req->buf) {
                return -ENODATA;
        } else
                pRequest->mapped = 0;
 
-       spin_lock_irqsave(&pThis->Lock, lockflags);
+       spin_lock_irqsave(&musb->Lock, lockflags);
 
        /* don't queue if the ep is down */
        if (!pEnd->desc) {
@@ -1190,10 +1206,10 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 
        /* it this is the head of the queue, start i/o ... */
        if (!pEnd->busy && &pRequest->request.list == pEnd->req_list.next)
-               musb_ep_restart(pThis, pRequest);
+               musb_ep_restart(musb, pRequest);
 
 cleanup:
-       spin_unlock_irqrestore(&pThis->Lock, lockflags);
+       spin_unlock_irqrestore(&musb->Lock, lockflags);
        return status;
 }
 
index 9b5dae9590cb1cd35596dd3f7be920e955a93382..5c7c7c32c4c43b77c145780240983cf62aad889c 100644 (file)
@@ -74,6 +74,7 @@ struct musb_ep {
        /* later things are modified based on usage */
        struct list_head                req_list;
 
+       /* true if lock must be dropped but req_list may not be advanced */
        u8                              busy;
 };
 
index b811005bb419dd999c18964908b0bda703526462..125199c6dbb9c56e9d0671ce5b03b92e61a16920 100644 (file)
@@ -33,7 +33,6 @@
  ******************************************************************/
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
@@ -284,7 +283,7 @@ __acquires(musb->Lock)
                        );
 
        spin_unlock(&musb->Lock);
-       usb_hcd_giveback_urb(musb_to_hcd(musb), urb, musb->int_regs);
+       usb_hcd_giveback_urb(musb_to_hcd(musb), urb);
        spin_lock(&musb->Lock);
 }
 
@@ -1485,8 +1484,8 @@ void musb_host_rx(struct musb *pThis, u8 bEnd)
        }
 
        if (unlikely(dma_channel_status(dma) == MGC_DMA_STATUS_BUSY)) {
-               /* SHOULD NEVER HAPPEN */
-               ERR("RX%d dma busy\n", bEnd);
+               /* SHOULD NEVER HAPPEN ... but at least DaVinci has done it */
+               ERR("RX%d dma busy, csr %04x\n", bEnd, wRxCsrVal);
                goto finish;
        }
 
@@ -1521,9 +1520,15 @@ void musb_host_rx(struct musb *pThis, u8 bEnd)
        }
 #endif
        if (dma && (wRxCsrVal & MGC_M_RXCSR_DMAENAB)) {
+               xfer_len = dma->dwActualLength;
+
+               wVal &= ~(MGC_M_RXCSR_DMAENAB
+                       | MGC_M_RXCSR_H_AUTOREQ
+                       | MGC_M_RXCSR_AUTOCLEAR
+                       | MGC_M_RXCSR_RXPKTRDY);
+               musb_writew(pEnd->regs, MGC_O_HDRC_RXCSR, wVal);
 
 #ifdef CONFIG_USB_INVENTRA_DMA
-               xfer_len = dma->dwActualLength;
                pUrb->actual_length += xfer_len;
                qh->offset += xfer_len;
 
@@ -1531,14 +1536,6 @@ void musb_host_rx(struct musb *pThis, u8 bEnd)
                bDone = (pUrb->actual_length >= pUrb->transfer_buffer_length)
                        || (dma->dwActualLength & (qh->maxpacket - 1));
 
-               wVal &= ~(MGC_M_RXCSR_DMAENAB
-                       | MGC_M_RXCSR_H_AUTOREQ
-                       | MGC_M_RXCSR_AUTOCLEAR
-                       | MGC_M_RXCSR_RXPKTRDY);
-
-               MGC_WriteCsr16(pBase, MGC_O_HDRC_RXCSR, bEnd, wVal);
-               MGC_WriteCsr16(pBase, MGC_O_HDRC_RXCSR, bEnd, wVal);
-
                /* send IN token for next packet, without AUTOREQ */
                if (!bDone) {
                        wVal |= MGC_M_RXCSR_H_REQPKT;
@@ -1552,7 +1549,6 @@ void musb_host_rx(struct musb *pThis, u8 bEnd)
                        MGC_ReadCsr16(pBase, MGC_O_HDRC_RXCOUNT, bEnd));
 #else
                bDone = TRUE;
-               xfer_len = dma->dwActualLength;
 #endif
        } else if (pUrb->status == -EINPROGRESS) {
                /* if no errors, be sure a packet is ready for unloading */
@@ -1682,7 +1678,7 @@ static int musb_schedule(
        int                     idle;
        int                     wBestDiff;
        int                     nBestEnd, nEnd;
-       struct musb_hw_ep       *hw_ep;
+       struct musb_hw_ep       *hw_ep = NULL;
        struct list_head        *head = NULL;
 
        /* use fixed hardware for control and bulk */
index d2e56a0cf8d16c9809dc8ba75e2c351105981b0a..4303cfcf52a72fef04519979bea06d614c98d578 100644 (file)
@@ -558,7 +558,7 @@ static int dump_header_stats(struct musb *pThis, char *buffer)
        code = sprintf(buffer,
                        "TUSB6010: devconf %08x, phy enable %08x drive %08x"
                        "\n\totg %03x timer %08x"
-                       "\n\tprcm conf %08x mgmt %08x; intmask %08x"
+                       "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
                        "\n",
                        musb_readl(pThis->ctrl_base, TUSB_DEV_CONF),
                        musb_readl(pThis->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
@@ -567,6 +567,7 @@ static int dump_header_stats(struct musb *pThis, char *buffer)
                        musb_readl(pThis->ctrl_base, TUSB_DEV_OTG_TIMER),
                        musb_readl(pThis->ctrl_base, TUSB_PRCM_CONF),
                        musb_readl(pThis->ctrl_base, TUSB_PRCM_MNGMT),
+                       musb_readl(pThis->ctrl_base, TUSB_INT_SRC),
                        musb_readl(pThis->ctrl_base, TUSB_INT_MASK));
        if (code <= 0)
                goto done;
index 5f1375c56f8dbb053ac13ce78dd583e82ff820bf..e31c3390fe17f6ee7e48cfa87c92766459130ba8 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 #include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/usb/musb.h>
 
 struct musb;
@@ -75,9 +75,6 @@ struct musb_ep;
 #include "otg.h"
 
 
-/* REVISIT tune this */
-#define        MIN_DMA_REQUEST         1       /* use PIO below this xfer size */
-
 
 #ifdef CONFIG_USB_MUSB_OTG
 
@@ -374,7 +371,7 @@ static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep)
 struct musb {
        spinlock_t              Lock;
        struct clk              *clock;
-       irqreturn_t             (*isr)(int, void *, struct pt_regs *);
+       irqreturn_t             (*isr)(int, void *);
        struct work_struct      irq_work;
 
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
@@ -418,7 +415,6 @@ struct musb {
        u8                      int_usb;
        u16                     int_rx;
        u16                     int_tx;
-       struct pt_regs          *int_regs;
 
        struct otg_transceiver  xceiv;
 
index 5e5c98799658ff4c3bb324358f80eeda42553e1e..f3436940086d6609092b9d1579977d26fed535e9 100644 (file)
@@ -21,7 +21,6 @@
  *
  */
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -29,9 +28,6 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/mach-types.h>
 #include <asm/arch/hardware.h>
index bb22005944e84443d1b19a224459391af992fc58..4d5cf148c70026ff92c1db39e62baac92180ce88 100644 (file)
@@ -94,7 +94,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -665,6 +664,7 @@ void musb_start(struct musb *musb)
        musb_writeb(regs, MGC_O_HDRC_POWER, MGC_M_POWER_ISOUPDATE
                                                | MGC_M_POWER_SOFTCONN
                                                | MGC_M_POWER_HSENAB
+                                               /* ENSUSPEND wedges tusb */
                                                // | MGC_M_POWER_ENSUSPEND
                                                );
 
@@ -672,7 +672,7 @@ void musb_start(struct musb *musb)
        devctl = musb_readb(regs, MGC_O_HDRC_DEVCTL);
        devctl &= ~MGC_M_DEVCTL_SESSION;
 
-       if (is_otg_enabled(pThis)) {
+       if (is_otg_enabled(musb)) {
                /* session started after:
                 * (a) ID-grounded irq, host mode;
                 * (b) vbus present/connect IRQ, peripheral mode;
@@ -683,7 +683,7 @@ void musb_start(struct musb *musb)
                else
                        devctl |= MGC_M_DEVCTL_SESSION;
 
-       } else if (is_host_enabled(pThis)) {
+       } else if (is_host_enabled(musb)) {
                /* assume ID pin is hard-wired to ground */
                devctl |= MGC_M_DEVCTL_SESSION;
 
@@ -1276,7 +1276,7 @@ static int __devinit musb_core_init(u16 wType, struct musb *pThis)
 
 #ifdef CONFIG_ARCH_OMAP243X
 
-static irqreturn_t generic_interrupt(int irq, void *__hci, struct pt_regs *r)
+static irqreturn_t generic_interrupt(int irq, void *__hci)
 {
        unsigned long   flags;
        irqreturn_t     retval = IRQ_NONE;
@@ -1287,7 +1287,6 @@ static irqreturn_t generic_interrupt(int irq, void *__hci, struct pt_regs *r)
        musb->int_usb = musb_readb(musb->pRegs, MGC_O_HDRC_INTRUSB);
        musb->int_tx = musb_readw(musb->pRegs, MGC_O_HDRC_INTRTX);
        musb->int_rx = musb_readw(musb->pRegs, MGC_O_HDRC_INTRRX);
-       musb->int_regs = r;
 
        if (musb->int_usb || musb->int_tx || musb->int_rx)
                retval = musb_interrupt(musb);
@@ -1604,7 +1603,6 @@ static void musb_free(struct musb *musb)
        if (is_dma_capable() && musb->pDmaController) {
                struct dma_controller   *c = musb->pDmaController;
 
-//
                (void) c->stop(c->pPrivateData);
                dma_controller_factory.destroy(c);
        }
@@ -1667,7 +1665,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        bad_config:
 #endif
        default:
-               dev_dbg(dev, "incompatible Kconfig role setting\n");
+               dev_err(dev, "incompatible Kconfig role setting\n");
                return -EINVAL;
        }
 
@@ -1811,8 +1809,9 @@ fail:
        INIT_WORK(&pThis->irq_work, musb_irq_work, pThis);
 
 #ifdef CONFIG_SYSFS
-       device_create_file(dev, &dev_attr_mode);
-       device_create_file(dev, &dev_attr_cable);
+       status = device_create_file(dev, &dev_attr_mode);
+       status = device_create_file(dev, &dev_attr_cable);
+       status = 0;
 #endif
 
        return status;
@@ -1828,6 +1827,10 @@ fail2:
  * bridge to a platform device; this driver then suffices.
  */
 
+#ifndef CONFIG_USB_INVENTRA_FIFO
+static u64     *orig_dma_mask;
+#endif
+
 static int __devinit musb_probe(struct platform_device *pdev)
 {
        struct device   *dev = &pdev->dev;
@@ -1845,12 +1848,17 @@ static int __devinit musb_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+#ifndef CONFIG_USB_INVENTRA_FIFO
+       /* clobbered by use_dma=n */
+       orig_dma_mask = dev->dma_mask;
+#endif
        return musb_init_controller(dev, irq, base);
 }
 
 static int __devexit musb_remove(struct platform_device *pdev)
 {
        struct musb     *musb = dev_to_musb(&pdev->dev);
+       void __iomem    *ctrl_base = musb->ctrl_base;
 
        /* this gets called on rmmod.
         *  - Host mode: host may still be active
@@ -1864,7 +1872,11 @@ static int __devexit musb_remove(struct platform_device *pdev)
                usb_remove_hcd(musb_to_hcd(musb));
 #endif
        musb_free(musb);
+       iounmap(ctrl_base);
        device_init_wakeup(&pdev->dev, 0);
+#ifndef CONFIG_USB_INVENTRA_FIFO
+       dev->dma_mask = orig_dma_mask;
+#endif
        return 0;
 }
 
index 22191040e488def572ca44f06b5d6782712d28d7..2eee49bc74ca906e0524bec8be291a56600dcd96 100644 (file)
@@ -146,6 +146,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
  * at most mA current to be drawn from VBUS during a Default-B session
  * (that is, while VBUS exceeds 4.4V).  In Default-A (including pure host
  * mode), or low power Default-B sessions, something else supplies power.
+ * Caller must take care of locking.
  */
 static int tusb_set_power(struct otg_transceiver *x, unsigned mA)
 {
@@ -178,7 +179,7 @@ static int tusb_set_power(struct otg_transceiver *x, unsigned mA)
  * (to be fixed in rev3 silicon) ... symptoms include disconnect
  * or looping suspend/resume cycles
  */
-static void tusb_set_clock_source(struct musb *musb, int mode)
+static void tusb_set_clock_source(struct musb *musb, unsigned mode)
 {
        void __iomem    *base = musb->ctrl_base;
        u32             reg;
@@ -186,10 +187,17 @@ static void tusb_set_clock_source(struct musb *musb, int mode)
        reg = musb_readl(base, TUSB_PRCM_CONF);
        reg &= ~TUSB_PRCM_CONF_SYS_CLKSEL(0x3);
 
+       /* 0 = refclk (clkin, XI)
+        * 1 = PHY 60 MHz (internal PLL)
+        * 2 = not supported
+        * 3 = NOR clock (huh?)
+        */
        if (mode > 0)
                reg |= TUSB_PRCM_CONF_SYS_CLKSEL(mode & 0x3);
 
        musb_writel(base, TUSB_PRCM_CONF, reg);
+
+       // FIXME tusb6010_platform_retime(mode == 0);
 }
 
 /*
@@ -477,7 +485,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *base)
        }
 }
 
-static irqreturn_t tusb_interrupt(int irq, void *__hci, struct pt_regs *r)
+static irqreturn_t tusb_interrupt(int irq, void *__hci)
 {
        struct musb     *musb = __hci;
        void __iomem    *base = musb->ctrl_base;
@@ -489,7 +497,6 @@ static irqreturn_t tusb_interrupt(int irq, void *__hci, struct pt_regs *r)
        int_src = musb_readl(base, TUSB_INT_SRC) & ~TUSB_INT_SRC_RESERVED_BITS;
        DBG(3, "TUSB IRQ %08x\n", int_src);
 
-       musb->int_regs = r;
        musb->int_usb = (u8) int_src;
 
        /* Acknowledge wake-up source interrupts */
@@ -570,7 +577,6 @@ static irqreturn_t tusb_interrupt(int irq, void *__hci, struct pt_regs *r)
        musb_writel(base, TUSB_INT_SRC_CLEAR,
                int_src & ~TUSB_INT_MASK_RESERVED_BITS);
 
-       musb->int_regs = NULL;
        musb_platform_try_idle(musb);
        spin_unlock_irqrestore(&musb->Lock, flags);
 
@@ -690,10 +696,10 @@ static int tusb_print_revision(struct musb *musb)
        return TUSB_REV_MAJOR(musb_readl(base, TUSB_INT_CTRL_REV));
 }
 
-static int tusb_start(struct musb *musb)
+static int __devinit tusb_start(struct musb *musb)
 {
        void __iomem    *base = musb->ctrl_base;
-       int             ret = -1;
+       int             ret = 0;
        unsigned long   flags;
        u32             reg;
 
@@ -701,7 +707,7 @@ static int tusb_start(struct musb *musb)
                ret = musb->board_set_power(1);
        if (ret != 0) {
                printk(KERN_ERR "tusb: Cannot enable TUSB6010\n");
-               goto err;
+               return ret;
        }
 
        spin_lock_irqsave(&musb->Lock, flags);
@@ -752,6 +758,8 @@ static int tusb_start(struct musb *musb)
        return 0;
 
 err:
+       spin_unlock_irqrestore(&musb->Lock, flags);
+
        if (musb->board_set_power)
                musb->board_set_power(0);