]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - sitara-epos/sitara-epos-kernel.git/blobdiff - drivers/usb/musb/musb_core.c
musb: select fifo_mode at runtime
[sitara-epos/sitara-epos-kernel.git] / drivers / usb / musb / musb_core.c
index b63ab1570103f2219afc5b44bdea08acd0531054..88e661ef4e69b6df56e902a8e8d032eb0f75eda4 100644 (file)
 
 #include "musb_core.h"
 
-#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
 
 
 #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
@@ -120,6 +119,10 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
 
+u8 (*musb_readb)(const void __iomem *addr, unsigned offset);
+EXPORT_SYMBOL_GPL(musb_readb);
+void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data);
+EXPORT_SYMBOL_GPL(musb_writeb);
 
 /*-------------------------------------------------------------------------*/
 
@@ -131,6 +134,44 @@ static inline struct musb *dev_to_musb(struct device *dev)
 /*-------------------------------------------------------------------------*/
 
 #ifndef CONFIG_BLACKFIN
+
+/*
+ * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum.
+ */
+static inline u8 __tusb_musb_readb(const void __iomem *addr, unsigned offset)
+{
+       u16 tmp;
+       u8 val;
+
+       tmp = __raw_readw(addr + (offset & ~1));
+       if (offset & 1)
+               val = (tmp >> 8);
+       else
+               val = tmp & 0xff;
+
+       return val;
+}
+
+static inline void __tusb_musb_writeb(void __iomem *addr, unsigned offset,
+                                       u8 data)
+{
+       u16 tmp;
+
+       tmp = __raw_readw(addr + (offset & ~1));
+       if (offset & 1)
+               tmp = (data << 8) | (tmp & 0xff);
+       else
+               tmp = (tmp & 0xff00) | data;
+
+       __raw_writew(tmp, addr + (offset & ~1));
+}
+
+static inline u8 __musb_readb(const void __iomem *addr, unsigned offset)
+       { return __raw_readb(addr + offset); }
+
+static inline void __musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+       { __raw_writeb(data, addr + offset); }
+
 static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset)
 {
        void __iomem *addr = otg->io_priv;
@@ -196,6 +237,12 @@ static int musb_ulpi_write(struct otg_transceiver *otg,
        return 0;
 }
 #else
+static inline u8 __musb_readb(const void __iomem *addr, unsigned offset)
+       { return (u8) (bfin_read16(addr + offset)); }
+
+static inline void __musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+       { bfin_write16(addr + offset, (u16) data); }
+
 #define musb_ulpi_read         NULL
 #define musb_ulpi_write                NULL
 #endif
@@ -205,10 +252,6 @@ static struct otg_io_access_ops musb_ulpi_access = {
        .write = musb_ulpi_write,
 };
 
-/*-------------------------------------------------------------------------*/
-
-#if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN)
-
 /*
  * Load an endpoint's FIFO
  */
@@ -249,8 +292,8 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
                writesb(fifo, src, len);
        }
 }
+EXPORT_SYMBOL_GPL(musb_write_fifo);
 
-#if !defined(CONFIG_USB_MUSB_AM35X)
 /*
  * Unload an endpoint's FIFO
  */
@@ -289,10 +332,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
                readsb(fifo, dst, len);
        }
 }
-#endif
-
-#endif /* normal PIO */
-
+EXPORT_SYMBOL_GPL(musb_read_fifo);
 
 /*-------------------------------------------------------------------------*/
 
@@ -320,14 +360,20 @@ void musb_load_testpacket(struct musb *musb)
 {
        void __iomem    *regs = musb->endpoints[0].regs;
 
-       musb_ep_select(musb->mregs, 0);
-       musb_write_fifo(musb->control_ep,
+       musb_ep_select(musb, musb->mregs, 0);
+       musb->ops->write_fifo(musb->control_ep,
                        sizeof(musb_test_packet), musb_test_packet);
        musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY);
 }
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * See also USB_OTG_1-3.pdf 6.6.5 Timers
+ * REVISIT: Are the other timers done in the hardware?
+ */
+#define TB_ASE0_BRST           100     /* Min 3.125 ms */
+
 /*
  * Handles OTG hnp timeouts, such as b_ase0_brst
  */
@@ -344,12 +390,9 @@ void musb_otg_timer_func(unsigned long data)
                musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
                musb->is_active = 0;
                break;
-       case OTG_STATE_A_SUSPEND:
        case OTG_STATE_A_WAIT_BCON:
-               dev_dbg(musb->controller, "HNP: %s timeout\n",
-                       otg_state_string(musb->xceiv->state));
-               musb_platform_set_vbus(musb, 0);
-               musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+               dev_dbg(musb->controller, "HNP: a_wait_bcon timeout; back to a_host\n");
+               musb_hnp_stop(musb);
                break;
        default:
                dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
@@ -359,8 +402,10 @@ void musb_otg_timer_func(unsigned long data)
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
+static DEFINE_TIMER(musb_otg_timer, musb_otg_timer_func, 0, 0);
+
 /*
- * Stops the HNP transition. Caller must take care of locking.
+ * Stops the B-device HNP state. Caller must take care of locking.
  */
 void musb_hnp_stop(struct musb *musb)
 {
@@ -368,13 +413,15 @@ void musb_hnp_stop(struct musb *musb)
        void __iomem    *mbase = musb->mregs;
        u8      reg;
 
-       dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
-
        switch (musb->xceiv->state) {
        case OTG_STATE_A_PERIPHERAL:
+       case OTG_STATE_A_WAIT_VFALL:
+       case OTG_STATE_A_WAIT_BCON:
+               dev_dbg(musb->controller, "HNP: Switching back to A-host\n");
                musb_g_disconnect(musb);
-               dev_dbg(musb->controller, "HNP: back to %s\n",
-                       otg_state_string(musb->xceiv->state));
+               musb->xceiv->state = OTG_STATE_A_IDLE;
+               MUSB_HST_MODE(musb);
+               musb->is_active = 0;
                break;
        case OTG_STATE_B_HOST:
                dev_dbg(musb->controller, "HNP: Disabling HR\n");
@@ -605,20 +652,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
                switch (musb->xceiv->state) {
                case OTG_STATE_A_PERIPHERAL:
-                       /* We also come here if the cable is removed, since
-                        * this silicon doesn't report ID-no-longer-grounded.
-                        *
-                        * We depend on T(a_wait_bcon) to shut us down, and
-                        * hope users don't do anything dicey during this
-                        * undesired detour through A_WAIT_BCON.
+                       /*
+                        * We cannot stop HNP here, devctl BDEVICE might be
+                        * still set.
                         */
-                       musb_hnp_stop(musb);
-                       usb_hcd_resume_root_hub(musb_to_hcd(musb));
-                       musb_root_disconnect(musb);
-                       musb_platform_try_idle(musb, jiffies
-                                       + msecs_to_jiffies(musb->a_wait_bcon
-                                               ? : OTG_TIME_A_WAIT_BCON));
-
                        break;
                case OTG_STATE_B_IDLE:
                        if (!musb->is_active)
@@ -630,9 +667,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                        if (musb->is_active) {
                                musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
                                dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
-                               mod_timer(&musb->otg_timer, jiffies
-                                       + msecs_to_jiffies(
-                                                       OTG_TIME_B_ASE0_BRST));
+                               musb_otg_timer.data = (unsigned long)musb;
+                               mod_timer(&musb_otg_timer, jiffies
+                                       + msecs_to_jiffies(TB_ASE0_BRST));
                        }
                        break;
                case OTG_STATE_A_WAIT_BCON:
@@ -683,23 +720,28 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                if (devctl & MUSB_DEVCTL_LSDEV)
                        musb->port1_status |= USB_PORT_STAT_LOW_SPEED;
 
+               if (hcd->status_urb)
+                       usb_hcd_poll_rh_status(hcd);
+               else
+                       usb_hcd_resume_root_hub(hcd);
+
+               MUSB_HST_MODE(musb);
+
                /* indicate new connection to OTG machine */
                switch (musb->xceiv->state) {
                case OTG_STATE_B_PERIPHERAL:
                        if (int_usb & MUSB_INTR_SUSPEND) {
                                dev_dbg(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n");
+                               musb->xceiv->state = OTG_STATE_B_HOST;
+                               hcd->self.is_b_host = 1;
                                int_usb &= ~MUSB_INTR_SUSPEND;
-                               goto b_host;
                        } else
                                dev_dbg(musb->controller, "CONNECT as b_peripheral???\n");
                        break;
                case OTG_STATE_B_WAIT_ACON:
-                       dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n");
-b_host:
+                       dev_dbg(musb->controller, "HNP: Waiting to switch to b_host state\n");
                        musb->xceiv->state = OTG_STATE_B_HOST;
                        hcd->self.is_b_host = 1;
-                       musb->ignore_disconnect = 0;
-                       del_timer(&musb->otg_timer);
                        break;
                default:
                        if ((devctl & MUSB_DEVCTL_VBUS)
@@ -710,13 +752,6 @@ b_host:
                        break;
                }
 
-               /* poke the root hub */
-               MUSB_HST_MODE(musb);
-               if (hcd->status_urb)
-                       usb_hcd_poll_rh_status(hcd);
-               else
-                       usb_hcd_resume_root_hub(hcd);
-
                dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
                                otg_state_string(musb->xceiv->state), devctl);
        }
@@ -737,16 +772,7 @@ b_host:
                                        + msecs_to_jiffies(musb->a_wait_bcon));
                        break;
                case OTG_STATE_B_HOST:
-                       /* REVISIT this behaves for "real disconnect"
-                        * cases; make sure the other transitions from
-                        * from B_HOST act right too.  The B_HOST code
-                        * in hnp_stop() is currently not used...
-                        */
-                       musb_root_disconnect(musb);
-                       musb_to_hcd(musb)->self.is_b_host = 0;
-                       musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
-                       MUSB_DEV_MODE(musb);
-                       musb_g_disconnect(musb);
+                       musb_hnp_stop(musb);
                        break;
                case OTG_STATE_A_PERIPHERAL:
                        musb_hnp_stop(musb);
@@ -756,6 +782,10 @@ b_host:
                        /* FALLTHROUGH */
                case OTG_STATE_B_PERIPHERAL:
                case OTG_STATE_B_IDLE:
+                       printk(KERN_INFO "musb %s gadget disconnected.\n",
+                               musb->gadget_driver
+                               ? musb->gadget_driver->driver.name
+                               : "");
                        musb_g_disconnect(musb);
                        break;
                default:
@@ -797,17 +827,14 @@ b_host:
                                musb_g_reset(musb);
                                /* FALLTHROUGH */
                        case OTG_STATE_A_WAIT_BCON:     /* OPT TD.4.7-900ms */
-                               /* never use invalid T(a_wait_bcon) */
-                               dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
-                                       otg_state_string(musb->xceiv->state),
-                                       TA_WAIT_BCON(musb));
-                               mod_timer(&musb->otg_timer, jiffies
-                                       + msecs_to_jiffies(TA_WAIT_BCON(musb)));
+                               dev_dbg(musb->controller, "HNP: Setting timer as %s\n",
+                                               otg_state_string(musb->xceiv->state));
+                               musb_otg_timer.data = (unsigned long)musb;
+                               mod_timer(&musb_otg_timer, jiffies
+                                               + msecs_to_jiffies(100));
                                break;
                        case OTG_STATE_A_PERIPHERAL:
-                               musb->ignore_disconnect = 0;
-                               del_timer(&musb->otg_timer);
-                               musb_g_reset(musb);
+                               musb_hnp_stop(musb);
                                break;
                        case OTG_STATE_B_WAIT_ACON:
                                dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
@@ -1009,22 +1036,10 @@ static void musb_shutdown(struct platform_device *pdev)
  * We don't currently use dynamic fifo setup capability to do anything
  * more than selecting one of a bunch of predefined configurations.
  */
-#if defined(CONFIG_USB_MUSB_TUSB6010)                  \
-       || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)     \
-       || defined(CONFIG_USB_MUSB_OMAP2PLUS)           \
-       || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE)    \
-       || defined(CONFIG_USB_MUSB_AM35X)               \
-       || defined(CONFIG_USB_MUSB_AM35X_MODULE)
-static ushort __initdata fifo_mode = 4;
-#elif defined(CONFIG_USB_MUSB_UX500)                   \
-       || defined(CONFIG_USB_MUSB_UX500_MODULE)
-static ushort __initdata fifo_mode = 5;
-#else
-static ushort __initdata fifo_mode = 2;
-#endif
+static short __devinitdata fifo_mode = -1;
 
 /* "modprobe ... fifo_mode=1" etc */
-module_param(fifo_mode, ushort, 0);
+module_param(fifo_mode, short, 0);
 MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
 
 /*
@@ -1033,7 +1048,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
  */
 
 /* mode 0 - fits in 2KB */
-static struct musb_fifo_cfg __initdata mode_0_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
@@ -1042,7 +1057,7 @@ static struct musb_fifo_cfg __initdata mode_0_cfg[] = {
 };
 
 /* mode 1 - fits in 4KB */
-static struct musb_fifo_cfg __initdata mode_1_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
@@ -1051,7 +1066,7 @@ static struct musb_fifo_cfg __initdata mode_1_cfg[] = {
 };
 
 /* mode 2 - fits in 4KB */
-static struct musb_fifo_cfg __initdata mode_2_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1061,7 +1076,7 @@ static struct musb_fifo_cfg __initdata mode_2_cfg[] = {
 };
 
 /* mode 3 - fits in 4KB */
-static struct musb_fifo_cfg __initdata mode_3_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
 { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },
 { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1071,7 +1086,7 @@ static struct musb_fifo_cfg __initdata mode_3_cfg[] = {
 };
 
 /* mode 4 - fits in 16KB */
-static struct musb_fifo_cfg __initdata mode_4_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
 { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1102,7 +1117,7 @@ static struct musb_fifo_cfg __initdata mode_4_cfg[] = {
 };
 
 /* mode 5 - fits in 8KB */
-static struct musb_fifo_cfg __initdata mode_5_cfg[] = {
+static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
 { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
 { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
 { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
@@ -1138,7 +1153,7 @@ static struct musb_fifo_cfg __initdata mode_5_cfg[] = {
  *
  * returns negative errno or offset for next fifo.
  */
-static int __init
+static int __devinit
 fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
                const struct musb_fifo_cfg *cfg, u16 offset)
 {
@@ -1209,18 +1224,20 @@ fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,
        return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
 }
 
-static struct musb_fifo_cfg __initdata ep0_cfg = {
+static struct musb_fifo_cfg __devinitdata ep0_cfg = {
        .style = FIFO_RXTX, .maxpacket = 64,
 };
 
-static int __init ep_config_from_table(struct musb *musb)
+static int __devinit ep_config_from_table(struct musb *musb)
 {
        const struct musb_fifo_cfg      *cfg;
        unsigned                i, n;
        int                     offset;
        struct musb_hw_ep       *hw_ep = musb->endpoints;
 
-       if (musb->config->fifo_cfg) {
+       if (musb->config->fifo_mode) {
+               fifo_mode = musb->config->fifo_mode;
+       } else if (musb->config->fifo_cfg) {
                cfg = musb->config->fifo_cfg;
                n = musb->config->fifo_cfg_size;
                goto done;
@@ -1299,12 +1316,11 @@ done:
        return 0;
 }
 
-
 /*
  * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
  * @param musb the controller
  */
-static int __init ep_config_from_hw(struct musb *musb)
+static int __devinit ep_config_from_hw(struct musb *musb)
 {
        u8 epnum = 0;
        struct musb_hw_ep *hw_ep;
@@ -1316,7 +1332,7 @@ static int __init ep_config_from_hw(struct musb *musb)
        /* FIXME pick up ep0 maxpacket size */
 
        for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
-               musb_ep_select(mbase, epnum);
+               musb_ep_select(musb, mbase, epnum);
                hw_ep = musb->endpoints + epnum;
 
                ret = musb_read_fifosize(musb, hw_ep, epnum);
@@ -1351,7 +1367,7 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
 /* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
  * configure endpoints, or take their config from silicon
  */
-static int __init musb_core_init(u16 musb_type, struct musb *musb)
+static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
 {
        u8 reg;
        char *type;
@@ -1431,20 +1447,25 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
        for (i = 0; i < musb->nr_endpoints; i++) {
                struct musb_hw_ep       *hw_ep = musb->endpoints + i;
 
-               hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
-#ifdef CONFIG_USB_MUSB_TUSB6010
-               hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
-               hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
-               hw_ep->fifo_sync_va =
-                       musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i);
-
-               if (i == 0)
-                       hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;
-               else
-                       hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2);
-#endif
+               if (musb->ops->flags & MUSB_GLUE_TUSB_STYLE) {
+                       hw_ep->fifo = MUSB_TUSB_FIFO_OFFSET(i) + mbase;
+                       hw_ep->fifo_async = musb->async +
+                                       0x400 + MUSB_TUSB_FIFO_OFFSET(i);
+                       hw_ep->fifo_sync = musb->sync +
+                                       0x400 + MUSB_TUSB_FIFO_OFFSET(i);
+                       hw_ep->fifo_sync_va = musb->sync_va + 0x400 +
+                                       MUSB_TUSB_FIFO_OFFSET(i);
+
+                       if (i == 0)
+                               hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;
+                       else
+                               hw_ep->conf = mbase + 0x400 +
+                                               (((i - 1) & 0xf) << 2);
+               } else {
+                       hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
+               }
 
-               hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
+               hw_ep->regs = MUSB_EP_OFFSET(musb, i, 0) + mbase;
                hw_ep->target_regs = musb_read_target_reg_base(i, mbase);
                hw_ep->rx_reinit = 1;
                hw_ep->tx_reinit = 1;
@@ -1546,7 +1567,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
        ep_num = 1;
        while (reg) {
                if (reg & 1) {
-                       /* musb_ep_select(musb->mregs, ep_num); */
+                       /* musb_ep_select(musb, musb->mregs, ep_num); */
                        /* REVISIT just retval = ep->rx_irq(...) */
                        retval = IRQ_HANDLED;
                        if (devctl & MUSB_DEVCTL_HM) {
@@ -1567,7 +1588,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
        ep_num = 1;
        while (reg) {
                if (reg & 1) {
-                       /* musb_ep_select(musb->mregs, ep_num); */
+                       /* musb_ep_select(musb, musb->mregs, ep_num); */
                        /* REVISIT just retval |= ep->tx_irq(...) */
                        retval = IRQ_HANDLED;
                        if (devctl & MUSB_DEVCTL_HM) {
@@ -1587,7 +1608,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
 EXPORT_SYMBOL_GPL(musb_interrupt);
 
 #ifndef CONFIG_MUSB_PIO_ONLY
-static int __initdata use_dma = 1;
+static int __devinitdata use_dma = 1;
 
 /* "modprobe ... use_dma=0" etc */
 module_param(use_dma, bool, 0);
@@ -1600,15 +1621,13 @@ void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
        /* called with controller lock already held */
 
        if (!epnum) {
-#ifndef CONFIG_USB_TUSB_OMAP_DMA
-               if (!is_cppi_enabled()) {
+               if (!tusb_dma_omap(musb) && !is_cppi_enabled(musb)) {
                        /* endpoint 0 */
                        if (devctl & MUSB_DEVCTL_HM)
                                musb_h_ep0_irq(musb);
                        else
                                musb_g_ep0_irq(musb);
                }
-#endif
        } else {
                /* endpoints 1..15 */
                if (transmit) {
@@ -1631,6 +1650,7 @@ void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
                }
        }
 }
+EXPORT_SYMBOL_GPL(musb_dma_completion);
 
 #else
 #define use_dma                        0
@@ -1691,8 +1711,7 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr,
        }
 
        spin_lock_irqsave(&musb->lock, flags);
-       /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */
-       musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ;
+       musb->a_wait_bcon = val;
        if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
                musb->is_active = 0;
        musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
@@ -1711,13 +1730,10 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
 
        spin_lock_irqsave(&musb->lock, flags);
        val = musb->a_wait_bcon;
-       /* FIXME get_vbus_status() is normally #defined as false...
-        * and is effectively TUSB-specific.
-        */
        vbus = musb_platform_get_vbus_status(musb);
        spin_unlock_irqrestore(&musb->lock, flags);
 
-       return sprintf(buf, "Vbus %s, timeout %lu msec\n",
+       return sprintf(buf, "Vbus %s, timeout %lu\n",
                        vbus ? "on" : "off", val);
 }
 static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
@@ -1774,7 +1790,7 @@ static void musb_irq_work(struct work_struct *data)
  * Init support
  */
 
-static struct musb *__init
+static struct musb *__devinit
 allocate_instance(struct device *dev,
                struct musb_hdrc_config *config, void __iomem *mbase)
 {
@@ -1797,7 +1813,6 @@ allocate_instance(struct device *dev,
        hcd->has_tt = 1;
 
        musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
-       musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
        dev_set_drvdata(dev, musb);
        musb->mregs = mbase;
        musb->ctrl_base = mbase;
@@ -1838,7 +1853,7 @@ static void musb_free(struct musb *musb)
                struct dma_controller   *c = musb->dma_controller;
 
                (void) c->stop(c);
-               dma_controller_destroy(c);
+               musb->ops->dma_controller_destroy(c);
        }
 
        kfree(musb);
@@ -1852,7 +1867,7 @@ static void musb_free(struct musb *musb)
  * @mregs: virtual address of controller registers,
  *     not yet corrected for platform-specific offsets
  */
-static int __init
+static int __devinit
 musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 {
        int                     status;
@@ -1884,6 +1899,18 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb->board_set_power = plat->set_power;
        musb->min_power = plat->min_power;
        musb->ops = plat->platform_ops;
+       if (fifo_mode == -1)
+               fifo_mode = musb->ops->fifo_mode;
+
+       if (musb->ops->flags & MUSB_GLUE_TUSB_STYLE) {
+               musb_readb = __tusb_musb_readb;
+               musb_writeb = __tusb_musb_writeb;
+       } else {
+               musb_readb = __musb_readb;
+               musb_writeb = __musb_writeb;
+       }
+
+       dev_info(dev, "dma type: %s\n", get_dma_name(musb));
 
        /* The musb_platform_init() call:
         *   - adjusts musb->mregs and musb->isr if needed,
@@ -1915,7 +1942,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        if (use_dma && dev->dma_mask) {
                struct dma_controller   *c;
 
-               c = dma_controller_create(musb, musb->mregs);
+               if (!musb->ops->dma_controller_create) {
+                       dev_err(dev, "no dma_controller_create for non-PIO mode!\n");
+                       status = -ENODEV;
+                       goto fail3;
+               }
+               c = musb->ops->dma_controller_create(musb, musb->mregs);
                musb->dma_controller = c;
                if (c)
                        (void) c->start(c);
@@ -1936,8 +1968,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        if (status < 0)
                goto fail3;
 
-       setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
-
        /* Init IRQ workqueue before request_irq */
        INIT_WORK(&musb->irq_work, musb_irq_work);
 
@@ -2012,8 +2042,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        if (status < 0)
                goto fail3;
 
-       pm_runtime_put(musb->controller);
-
        status = musb_init_debugfs(musb);
        if (status < 0)
                goto fail4;
@@ -2036,6 +2064,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
                        ? "DMA" : "PIO",
                        musb->nIrq);
 
+       if (status == 0)
+               musb_debug_create("driver/musb_hdrc", musb);
+
        return 0;
 
 fail5:
@@ -2074,7 +2105,7 @@ fail0:
 static u64     *orig_dma_mask;
 #endif
 
-static int __init musb_probe(struct platform_device *pdev)
+static int __devinit musb_probe(struct platform_device *pdev)
 {
        struct device   *dev = &pdev->dev;
        int             irq = platform_get_irq_byname(pdev, "mc");
@@ -2116,6 +2147,7 @@ static int __exit musb_remove(struct platform_device *pdev)
        pm_runtime_get_sync(musb->controller);
        musb_exit_debugfs(musb);
        musb_shutdown(pdev);
+       musb_debug_delete("driver/musb_hdrc", musb);
 
        pm_runtime_put(musb->controller);
        musb_free(musb);
@@ -2158,6 +2190,7 @@ static void musb_save_context(struct musb *musb)
                if (!epio)
                        continue;
 
+               musb_writeb(musb_base, MUSB_INDEX, i);
                musb->context.index_regs[i].txmaxp =
                        musb_readw(epio, MUSB_TXMAXP);
                musb->context.index_regs[i].txcsr =
@@ -2233,6 +2266,7 @@ static void musb_restore_context(struct musb *musb)
                if (!epio)
                        continue;
 
+               musb_writeb(musb_base, MUSB_INDEX, i);
                musb_writew(epio, MUSB_TXMAXP,
                        musb->context.index_regs[i].txmaxp);
                musb_writew(epio, MUSB_TXCSR,
@@ -2363,6 +2397,7 @@ static struct platform_driver musb_driver = {
                .owner          = THIS_MODULE,
                .pm             = MUSB_DEV_PM_OPS,
        },
+       .probe      = musb_probe,
        .remove         = __exit_p(musb_remove),
        .shutdown       = musb_shutdown,
 };
@@ -2379,7 +2414,7 @@ static int __init musb_init(void)
                ", "
                "otg (peripheral+host)",
                musb_driver_name);
-       return platform_driver_probe(&musb_driver, musb_probe);
+       return platform_driver_register(&musb_driver);
 }
 
 /* make us init after usbcore and i2c (transceivers, regulators, etc)