ChangeSet 1.2000.12.6, 2004/10/21 13:29:21-07:00, [EMAIL PROTECTED]

[PATCH] USB: omap_udc updates

This is a collection of updates to the OMAP UDC driver.

  - OMAP-1510 support, including DMA (the DMA controller isn't quite
    the same as on newer chips) but not double buffering.

  - Some PIO work:

      * fix some races that showed up on OMAP-1510

      * tracking down annoying PIO-OUT lossage and making double buffering
        start to behave (needed as fallback if all DMA channels are in use).

  - DMA-IN works on both 1510 and 16xx

Plus minor cleanups.

Signed-off-by: David Brownell <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>


 drivers/usb/gadget/omap_udc.c |  335 ++++++++++++++++++++++++++++++------------
 drivers/usb/gadget/omap_udc.h |    6 
 2 files changed, 249 insertions(+), 92 deletions(-)


diff -Nru a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
--- a/drivers/usb/gadget/omap_udc.c     2004-10-22 16:12:44 -07:00
+++ b/drivers/usb/gadget/omap_udc.c     2004-10-22 16:12:44 -07:00
@@ -59,15 +59,14 @@
 
 #undef USB_TRACE
 
-/* OUT-dma seems to be behaving */
+/* bulk DMA seems to be behaving for both IN and OUT */
 #define        USE_DMA
 
 /* ISO too */
 #define        USE_ISO
 
-
 #define        DRIVER_DESC     "OMAP UDC driver"
-#define        DRIVER_VERSION  "24 August 2004"
+#define        DRIVER_VERSION  "4 October 2004"
 
 #define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
 
@@ -104,7 +103,6 @@
 module_param (fifo_mode, uint, 0);
 MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)");
 
-
 #ifdef USE_DMA
 static unsigned use_dma = 1;
 
@@ -224,18 +222,17 @@
                list_add(&ep->iso, &udc->iso);
 
        /* maybe assign a DMA channel to this endpoint */
-       if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-                       && !(ep->bEndpointAddress & USB_DIR_IN))
-                       /* FIXME ISO can dma, but prefers first channel.
-                        * IN can dma, but lacks debugging.
-                        */
+       if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK)
+               /* FIXME ISO can dma, but prefers first channel */
                dma_channel_claim(ep, 0);
 
        /* PIO OUT may RX packets */
        if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC
                        && !ep->has_dma
-                       && !(ep->bEndpointAddress & USB_DIR_IN))
+                       && !(ep->bEndpointAddress & USB_DIR_IN)) {
                UDC_CTRL_REG = UDC_SET_FIFO_EN;
+               ep->ackwait = 1 + ep->double_buf;
+       }
 
        spin_unlock_irqrestore(&udc->lock, flags);
        VDBG("%s enabled\n", _ep->name);
@@ -262,6 +259,7 @@
        ep->has_dma = 0;
        UDC_CTRL_REG = UDC_SET_HALT;
        list_del_init(&ep->iso);
+       del_timer(&ep->timer);
 
        spin_unlock_irqrestore(&ep->udc->lock, flags);
 
@@ -498,17 +496,22 @@
                u16     ep_stat = UDC_STAT_FLG_REG;
 
                is_last = 0;
-               if (ep_stat & FIFO_UNREADABLE)
+               if (ep_stat & FIFO_EMPTY) {
+                       if (!ep->double_buf)
+                               break;
+                       ep->fnf = 1;
+               }
+               if (ep_stat & UDC_EP_HALTED)
                        break;
 
-               if (ep_stat & (UDC_NON_ISO_FIFO_FULL|UDC_ISO_FIFO_FULL))
+               if (ep_stat & FIFO_FULL)
                        avail = ep->ep.maxpacket;
-               else 
+               else  {
                        avail = UDC_RXFSTAT_REG;
+                       ep->fnf = ep->double_buf;
+               }
                count = read_packet(buf, req, avail);
 
-               // FIXME double buffered PIO OUT wasn't behaving...
-
                /* partial packet reads may not be errors */
                if (count < ep->ep.maxpacket) {
                        is_last = 1;
@@ -526,26 +529,56 @@
 
                if (!ep->bEndpointAddress)
                        break;
-               if (!ep->double_buf) {
-                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
-                       if (!is_last)
-                               break;
-               }
-
-               if (is_last) {
+               if (is_last)
                        done(ep, req, 0);
-                       if (list_empty(&ep->queue) || !ep->double_buf)
-                               break;
-                       req = container_of(ep->queue.next,
-                                       struct omap_req, queue);
-                       is_last = 0;
-               }
+               break;
        }
        return is_last;
 }
 
 /*-------------------------------------------------------------------------*/
 
+static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
+{
+       dma_addr_t      end;
+
+       /* IN-DMA needs this on fault/cancel paths, so 15xx misreports
+        * the last transfer's bytecount by more than a FIFO's worth.
+        */
+       if (cpu_is_omap15xx())
+               return 0;
+
+       end = omap_readw(OMAP_DMA_CSAC(ep->lch));
+       if (end == ep->dma_counter)
+               return 0;
+
+       end |= start & (0xffff << 16);
+       if (end < start)
+               end += 0x10000;
+       return end - start;
+}
+
+#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \
+               ? OMAP_DMA_CSAC(x) /* really: CPC */ \
+               : OMAP_DMA_CDAC(x))
+
+static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
+{
+       dma_addr_t      end;
+
+       end = omap_readw(DMA_DEST_LAST(ep->lch));
+       if (end == ep->dma_counter)
+               return 0;
+
+       end |= start & (0xffff << 16);
+       if (cpu_is_omap15xx())
+               end++;
+       if (end < start)
+               end += 0x10000;
+       return end - start;
+}
+
+
 /* Each USB transfer request using DMA maps to one or more DMA transfers.
  * When DMA completion isn't request completion, the UDC continues with
  * the next DMA transfer for that USB transfer.
@@ -555,26 +588,29 @@
 {
        u16             txdma_ctrl;
        unsigned        length = req->req.length - req->req.actual;
+       const int       sync_mode = cpu_is_omap15xx()
+                               ? OMAP_DMA_SYNC_FRAME
+                               : OMAP_DMA_SYNC_ELEMENT;
 
        /* measure length in either bytes or packets */
-       if (length <= (UDC_TXN_TSC + 1)) {
+       if ((cpu_is_omap16xx() && length <= (UDC_TXN_TSC + 1))
+                       || (cpu_is_omap15xx() && length < ep->maxpacket)) {
                txdma_ctrl = UDC_TXN_EOT | length;
                omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-                               length, 1, OMAP_DMA_SYNC_ELEMENT);
+                               length, 1, sync_mode);
        } else {
-               length = max(length / ep->maxpacket,
+               length = min(length / ep->maxpacket,
                                (unsigned) UDC_TXN_TSC + 1);
                txdma_ctrl = length;
                omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-                               ep->ep.maxpacket, length,
-                               OMAP_DMA_SYNC_ELEMENT);
+                               ep->ep.maxpacket, length, sync_mode);
                length *= ep->maxpacket;
        }
-
        omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
                OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
 
        omap_start_dma(ep->lch);
+       ep->dma_counter = omap_readw(OMAP_DMA_CSAC(ep->lch));
        UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel);
        UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl;
        req->dma_bytes = length;
@@ -592,14 +628,9 @@
                                && req->dma_bytes != 0
                                && (req->req.actual % ep->maxpacket) == 0)
                        return;
-       } else {
-               u32     last;
-
-               // FIXME this surely isn't #bytes transferred
-               last = (omap_readw(OMAP_DMA_CSSA_U(ep->lch)) << 16)
-                               | omap_readw(OMAP_DMA_CSSA_L(ep->lch));
-               req->req.actual = last - req->req.dma;
-       }
+       } else
+               req->req.actual += dma_src_len(ep, req->req.dma
+                                                       + req->req.actual);
 
        /* tx completion */
        omap_stop_dma(ep->lch);
@@ -624,6 +655,7 @@
                        OMAP_DMA_SYNC_ELEMENT);
        omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
                OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+       ep->dma_counter = omap_readw(DMA_DEST_LAST(ep->lch));
 
        UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
        UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel);
@@ -638,15 +670,13 @@
 {
        u16     count;
 
-       /* FIXME must be a better way to see how much dma
-        * happened, even when it never got going...
-        */
-       count = omap_readw(OMAP_DMA_CDAC(ep->lch));
-       count -= 0xffff & (req->req.dma + req->req.actual);
+       if (status == 0)
+               ep->dma_counter = (u16) (req->req.dma + req->req.actual);
+       count = dma_dest_len(ep, req->req.dma + req->req.actual);
        count += req->req.actual;
        if (count <= req->req.length)
                req->req.actual = count;
-       
+
        if (count != req->dma_bytes || status)
                omap_stop_dma(ep->lch);
 
@@ -705,7 +735,9 @@
 
        if (irq_src & UDC_RXN_CNT) {
                ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
-               DBG("%s, RX_CNT irq?\n", ep->ep.name);
+               ep->irqs++;
+               /* omap15xx does this unasked... */
+               VDBG("%s, RX_CNT irq?\n", ep->ep.name);
                UDC_IRQ_SRC_REG = UDC_RXN_CNT;
        }
 }
@@ -778,7 +810,8 @@
                omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
 
                /* channel type P: hw synch (fifo) */
-               omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+               if (!cpu_is_omap15xx())
+                       omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
        }
 
 just_restart:
@@ -803,6 +836,10 @@
                        use_ep(ep, UDC_EP_SEL);
                        (is_in ? write_fifo : read_fifo)(ep, req);
                        deselect_ep();
+                       if (!is_in) {
+                               UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                               ep->ackwait = 1 + ep->double_buf;
+                       }
                        /* IN: 6 wait states before it'll tx */
                }
        }
@@ -833,24 +870,21 @@
                UDC_TXDMA_CFG_REG &= ~mask;
 
                if (req) {
-                       if (active)
-                               udelay(50);
                        finish_in_dma(ep, req, -ECONNRESET);
-                       if (UDC_TXDMA_CFG_REG & mask)
-                               WARN("%s, SPIN abort TX dma\n", ep->ep.name);
-               }
 
-               /* host may empty the fifo (or not...) */
+                       /* clear FIFO; hosts probably won't empty it */
+                       use_ep(ep, UDC_EP_SEL);
+                       UDC_CTRL_REG = UDC_CLR_EP;
+                       deselect_ep();
+               }
                while (UDC_TXDMA_CFG_REG & mask)
                        udelay(10);
-
        } else {
                UDC_RXDMA_CFG_REG &= ~mask;
 
                /* dma empties the fifo */
-               while (active && (UDC_RXDMA_CFG_REG & mask))
+               while (UDC_RXDMA_CFG_REG & mask)
                        udelay(10);
-               omap_stop_dma(ep->lch);
                if (req)
                        finish_out_dma(ep, req, -ECONNRESET);
        }
@@ -997,6 +1031,10 @@
                        if ((is_in ? write_fifo : read_fifo)(ep, req) == 1)
                                req = 0;
                        deselect_ep();
+                       if (!is_in) {
+                               UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                               ep->ackwait = 1 + ep->double_buf;
+                       }
                        /* IN: 6 wait states before it'll tx */
                }
        }
@@ -1034,7 +1072,7 @@
        if (use_dma && ep->dma_channel && ep->queue.next == &req->queue) {
                int channel = ep->dma_channel;
 
-               /* releasing the dma completion cancels the request,
+               /* releasing the channel cancels the request,
                 * reclaiming the channel restarts the queue
                 */
                dma_channel_release(ep);
@@ -1104,8 +1142,10 @@
                        use_ep(ep, 0);
                        UDC_CTRL_REG = UDC_RESET_EP;
                        ep->ackwait = 0;
-                       if (!(ep->bEndpointAddress & USB_DIR_IN))
+                       if (!(ep->bEndpointAddress & USB_DIR_IN)) {
                                UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                               ep->ackwait = 1 + ep->double_buf;
+                       }
                }
        }
 done:
@@ -1218,7 +1258,7 @@
 
 /*
  * Called by whatever detects VBUS sessions:  external transceiver
- * driver, or maybe GPIO0 VBUS IRQ.
+ * driver, or maybe GPIO0 VBUS IRQ.  May request 48 MHz clock.
  */
 static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
 {
@@ -1229,6 +1269,13 @@
        spin_lock_irqsave(&udc->lock, flags);
        VDBG("VBUS %s\n", is_active ? "on" : "off");
        udc->vbus_active = (is_active != 0);
+       if (cpu_is_omap15xx()) {
+               /* "software" detect, ignored if !VBUS_MODE_1510 */
+               if (is_active)
+                       FUNC_MUX_CTRL_0_REG |= VBUS_CTRL_1510;
+               else
+                       FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
+       }
        if (can_pullup(udc))
                pullup_enable(udc);
        else
@@ -1342,8 +1389,15 @@
        /* Clear any pending requests and then scrub any rx/tx state
         * before starting to handle the SETUP request.
         */
-       if (irq_src & UDC_SETUP)
+       if (irq_src & UDC_SETUP) {
+               u16     ack = irq_src & (UDC_EP0_TX|UDC_EP0_RX);
+
                nuke(ep0, 0);
+               if (ack) {
+                       UDC_IRQ_SRC_REG = ack;
+                       irq_src = UDC_SETUP;
+               }
+       }
 
        /* IN/OUT packets mean we're in the DATA or STATUS stage.  
         * This driver uses only uses protocol stalls (ep0 never halts),
@@ -1508,8 +1562,10 @@
                                use_ep(ep, 0);
                                UDC_CTRL_REG = UDC_RESET_EP;
                                ep->ackwait = 0;
-                               if (!(ep->bEndpointAddress & USB_DIR_IN))
+                               if (!(ep->bEndpointAddress & USB_DIR_IN)) {
                                        UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                                       ep->ackwait = 1 + ep->double_buf;
+                               }
                        }
                        VDBG("%s halt cleared by host\n", ep->name);
                        goto ep0out_status_stage;
@@ -1743,6 +1799,39 @@
        return status;
 }
 
+/* workaround for seemingly-lost IRQs for RX ACKs... */
+#define PIO_OUT_TIMEOUT        (jiffies + HZ/3)
+#define HALF_FULL(f)   (!((f)&(UDC_NON_ISO_FIFO_FULL|UDC_NON_ISO_FIFO_EMPTY)))
+
+static void pio_out_timer(unsigned long _ep)
+{
+       struct omap_ep  *ep = (void *) _ep;
+       unsigned long   flags;
+       u16             stat_flg;
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+       if (!list_empty(&ep->queue) && ep->ackwait) {
+               use_ep(ep, 0);
+               stat_flg = UDC_STAT_FLG_REG;
+
+               if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
+                               || (ep->double_buf && HALF_FULL(stat_flg)))) {
+                       struct omap_req *req;
+
+                       VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
+                       req = container_of(ep->queue.next,
+                                       struct omap_req, queue);
+                       UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL;
+                       (void) read_fifo(ep, req);
+                       UDC_EP_NUM_REG = ep->bEndpointAddress;
+                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                       ep->ackwait = 1 + ep->double_buf;
+               }
+       }
+       mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
+       spin_unlock_irqrestore(&ep->udc->lock, flags);
+}
+
 static irqreturn_t
 omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r)
 {
@@ -1766,38 +1855,56 @@
                ep = &udc->ep[epnum];
                ep->irqs++;
 
-               if (!list_empty(&ep->queue)) {
-                       UDC_EP_NUM_REG = epnum | UDC_EP_SEL;
-                       if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+               UDC_EP_NUM_REG = epnum | UDC_EP_SEL;
+               ep->fnf = 0;
+               if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+                       ep->ackwait--;
+                       if (!list_empty(&ep->queue)) {
                                int stat;
                                req = container_of(ep->queue.next,
                                                struct omap_req, queue);
                                stat = read_fifo(ep, req);
-                               // FIXME double buffered PIO OUT should work
+                               if (!ep->double_buf)
+                                       ep->fnf = 1;
                        }
-                       UDC_EP_NUM_REG = epnum;
                }
+               /* min 6 clock delay before clearing EP_SEL ... */
+               epn_stat = UDC_EPN_STAT_REG;
+               epn_stat = UDC_EPN_STAT_REG;
+               UDC_EP_NUM_REG = epnum;
+
+               /* enabling fifo _after_ clearing ACK, contrary to docs,
+                * reduces lossage; timer still needed though (sigh).
+                */
+               if (ep->fnf) {
+                       UDC_CTRL_REG = UDC_SET_FIFO_EN;
+                       ep->ackwait = 1 + ep->double_buf;
+               }
+               mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
        }
 
        /* then IN transfers */
-       if (irq_src & UDC_EPN_TX) {
+       else if (irq_src & UDC_EPN_TX) {
                epnum = epn_stat & 0x0f;
                UDC_IRQ_SRC_REG = UDC_EPN_TX;
                status = IRQ_HANDLED;
                ep = &udc->ep[16 + epnum];
                ep->irqs++;
-               ep->ackwait = 0;
 
-               if (!list_empty(&ep->queue)) {
-                       UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL;
-                       if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+               UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL;
+               if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+                       ep->ackwait = 0;
+                       if (!list_empty(&ep->queue)) {
                                req = container_of(ep->queue.next,
                                                struct omap_req, queue);
                                (void) write_fifo(ep, req);
                        }
-                       UDC_EP_NUM_REG = epnum | UDC_EP_DIR;
-                       /* 6 wait states before it'll tx */
                }
+               /* min 6 clock delay before clearing EP_SEL ... */
+               epn_stat = UDC_EPN_STAT_REG;
+               epn_stat = UDC_EPN_STAT_REG;
+               UDC_EP_NUM_REG = epnum | UDC_EP_DIR;
+               /* then 6 clocks before it'd tx */
        }
 
        spin_unlock_irqrestore(&udc->lock, flags);
@@ -1939,6 +2046,9 @@
                        pullup_disable (udc);
        }
 
+       if (machine_is_omap_innovator())
+               omap_vbus_session(&udc->gadget, 1);
+
 done:
        return status;
 }
@@ -1954,6 +2064,9 @@
        if (!driver || driver != udc->driver)
                return -EINVAL;
 
+       if (machine_is_omap_innovator())
+               omap_vbus_session(&udc->gadget, 0);
+
        if (udc->transceiver)
                (void) otg_set_peripheral(udc->transceiver, 0);
        else
@@ -2002,8 +2115,16 @@
 
        stat_flg = UDC_STAT_FLG_REG;
        seq_printf(s,
-               "\n%s %sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
-               ep->name, buf, ep->irqs, stat_flg,
+               "\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
+               ep->name, buf,
+               ep->double_buf ? "dbuf " : "",
+               ({char *s; switch(ep->ackwait){
+               case 0: s = ""; break;
+               case 1: s = "(ackw) "; break;
+               case 2: s = "(ackw2) "; break;
+               default: s = "(?) "; break;
+               } s;}),
+               ep->irqs, stat_flg,
                (stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
                (stat_flg & UDC_MISS_IN) ? "miss_in " : "",
                (stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "",
@@ -2021,10 +2142,19 @@
        if (list_empty (&ep->queue))
                seq_printf(s, "\t(queue empty)\n");
        else
-               list_for_each_entry (req, &ep->queue, queue)
+               list_for_each_entry (req, &ep->queue, queue) {
+                       unsigned        length = req->req.actual;
+
+                       if (use_dma && buf[0]) {
+                               length += ((ep->bEndpointAddress & USB_DIR_IN)
+                                               ? dma_src_len : dma_dest_len)
+                                       (ep, req->req.dma + length);
+                               buf[0] = 0;
+                       }
                        seq_printf(s, "\treq %p len %d/%d buf %p\n",
-                                       &req->req, req->req.actual,
+                                       &req->req, length,
                                        req->req.length, req->req.buf);
+               }
 }
 
 static char *trx_mode(unsigned m)
@@ -2125,7 +2255,11 @@
                fifo_mode,
                udc->driver ? udc->driver->driver.name : "(none)",
                HMC,
-               udc->transceiver ? udc->transceiver->label : "");
+               udc->transceiver ? udc->transceiver->label : "(none)");
+       seq_printf(s, "ULPD control %04x req %04x status %04x\n",
+               __REG16(ULPD_CLOCK_CTRL),
+               __REG16(ULPD_SOFT_REQ),
+               __REG16(ULPD_STATUS_REQ));
 
        /* OTG controller registers */
        if (!cpu_is_omap15xx())
@@ -2305,10 +2439,10 @@
                epn_rxtx |= UDC_EPN_RX_ISO;
                dbuf = 1;
        } else {
-               /* pio-out could potentially double-buffer,
-                * as can (should!) DMA-IN
+               /* double-buffering "not supported" on 15xx,
+                * and ignored for PIO-IN on 16xx
                 */
-               if (!use_dma || (addr & USB_DIR_IN))
+               if (!use_dma || cpu_is_omap15xx())
                        dbuf = 0;
 
                switch (maxp) {
@@ -2320,6 +2454,9 @@
                }
                if (dbuf && addr)
                        epn_rxtx |= UDC_EPN_RX_DB;
+               init_timer(&ep->timer);
+               ep->timer.function = pio_out_timer;
+               ep->timer.data = (unsigned long) ep;
        }
        if (addr)
                epn_rxtx |= UDC_EPN_RX_VALID;
@@ -2509,23 +2646,35 @@
                return -EBUSY;
        }
 
-       INFO("OMAP UDC rev %d.%d, %s receptacle\n",
+       INFO("OMAP UDC rev %d.%d%s\n",
                UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
-               config->otg ? "Mini-AB" : "B/Mini-B");
+               config->otg ? ", Mini-AB" : "");
 
        /* use the mode given to us by board init code */
        if (cpu_is_omap15xx()) {
                hmc = HMC_1510;
                type = "(unknown)";
 
-               /* FIXME may need a GPIO-0 handler to call
-                * usb_gadget_vbus_{dis,}connect() on us...
-                */
+               if (machine_is_omap_innovator()) {
+                       /* just set up software VBUS detect, and then
+                        * later rig it so we always report VBUS.
+                        * FIXME without really sensing VBUS, we can't
+                        * know when to turn PULLUP_EN on/off; and that
+                        * means we always "need" the 48MHz clock.
+                        */
+                       u32 tmp = FUNC_MUX_CTRL_0_REG;
+
+                       FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
+                       tmp |= VBUS_MODE_1510;
+                       tmp &= ~VBUS_CTRL_1510;
+                       FUNC_MUX_CTRL_0_REG = tmp;
+               }
        } else {
                hmc = HMC_1610;
                switch (hmc) {
                case 3:
                case 11:
+               case 16:
                case 19:
                case 25:
                        xceiv = otg_get_transceiver();
@@ -2565,7 +2714,9 @@
        xceiv = 0;
        // "udc" is now valid
        pullup_disable(udc);
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        udc->gadget.is_otg = (config->otg != 0);
+#endif
 
        /* USB general purpose IRQ:  ep0, state changes, dma, etc */
        status = request_irq(odev->resource[1].start, omap_udc_irq,
@@ -2694,7 +2845,11 @@
 
 static int __init udc_init(void)
 {
-       INFO("%s, version: " DRIVER_VERSION "%s\n", driver_desc,
+       INFO("%s, version: " DRIVER_VERSION
+#ifdef USE_ISO
+               " (iso)"
+#endif
+               "%s\n", driver_desc,
                use_dma ?  " (dma)" : "");
        return driver_register(&udc_driver);
 }
diff -Nru a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
--- a/drivers/usb/gadget/omap_udc.h     2004-10-22 16:12:44 -07:00
+++ b/drivers/usb/gadget/omap_udc.h     2004-10-22 16:12:44 -07:00
@@ -146,11 +146,14 @@
        u8                              bmAttributes;
        unsigned                        double_buf:1;
        unsigned                        stopped:1;
-       unsigned                        ackwait:1;
+       unsigned                        fnf:1;
        unsigned                        has_dma:1;
+       u8                              ackwait;
        u8                              dma_channel;
+       u16                             dma_counter;
        int                             lch;
        struct omap_udc                 *udc;
+       struct timer_list               timer;
 };
 
 struct omap_udc {
@@ -168,7 +171,6 @@
        unsigned                        ep0_set_config:1;
        unsigned                        ep0_reset_config:1;
        unsigned                        ep0_setup:1;
-       unsigned                        hmc:6;
 
        struct completion               *done;
 };



-------------------------------------------------------
This SF.net email is sponsored by: IT Product Guide on ITManagersJournal
Use IT products in your business? Tell us what you think of them. Give us
Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more
http://productguide.itmanagersjournal.com/guidepromo.tmpl
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to