]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
MUSB: Update register access based on new HDRC core spec
authorDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 5 Sep 2006 11:07:15 +0000 (14:07 +0300)
committerTony Lindgren <tony@atomide.com>
Tue, 5 Sep 2006 14:21:35 +0000 (17:21 +0300)
Catch up to info from latest HDRC core spec ... some new registers
and fields, and constraints notably

 - not clearing TX fifo unless it's empty (that might explain some
   host side glitching).

 - not all POWER fields are writable

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
drivers/usb/musb/g_ep0.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musbhdrc.h
drivers/usb/musb/plat_uds.c
drivers/usb/musb/virthub.c

index 35153c5f47a27f93dd8da922468f844a726b539e..fc6a7c0bf10c0e01aafd5eeeb709e79b28c75526 100644 (file)
@@ -387,9 +387,10 @@ stall:
                                if (is_in) {
                                        csr = musb_readw(regs,
                                                        MGC_O_HDRC_TXCSR);
+                                       if (csr & MGC_M_TXCSR_FIFONOTEMPTY)
+                                               csr |= MGC_M_TXCSR_FLUSHFIFO;
                                        csr |= MGC_M_TXCSR_P_SENDSTALL
                                                | MGC_M_TXCSR_CLRDATATOG
-                                               | MGC_M_TXCSR_FLUSHFIFO
                                                | MGC_M_TXCSR_P_WZC_BITS;
                                        musb_writew(regs, MGC_O_HDRC_TXCSR,
                                                        csr);
index bd889aeeed9d00d997000572b3169706c7b1b8f3..24a07ccb5ade7a5886596f2510633e796a40f2df 100644 (file)
@@ -297,11 +297,12 @@ static void txstate(struct musb *pThis, struct musb_request *req)
                                        pRequest->dma, request_size);
                        if (use_dma) {
                                if (pEnd->dma->bDesiredMode == 0) {
+                                       /* ASSERT: DMAENAB is clear */
                                        wCsrVal &= ~(MGC_M_TXCSR_AUTOSET |
                                                        MGC_M_TXCSR_DMAMODE);
                                        wCsrVal |= (MGC_M_TXCSR_DMAENAB |
                                                        MGC_M_TXCSR_MODE);
-                                               // against programming guide
+                                       // against programming guide
                                }
                                else
                                        wCsrVal |= (MGC_M_TXCSR_AUTOSET
@@ -347,6 +348,7 @@ static void txstate(struct musb *pThis, struct musb_request *req)
                if (!use_dma) {
                        c->channel_release(pEnd->dma);
                        pEnd->dma = NULL;
+                       /* ASSERT: DMAENAB clear */
                        wCsrVal &= ~(MGC_M_TXCSR_DMAMODE | MGC_M_TXCSR_MODE);
                        /* invariant: prequest->buf is non-null */
                }
@@ -837,8 +839,10 @@ done:
 static int musb_gadget_enable(struct usb_ep *ep,
                        const struct usb_endpoint_descriptor *desc)
 {
-       unsigned long flags;
-       struct musb_ep  *pEnd;
+       unsigned long           flags;
+       struct musb_ep          *pEnd;
+       struct musb_hw_ep       *hw_ep;
+       void __iomem            *regs;
        struct musb     *pThis;
        void __iomem    *pBase;
        u8              bEnd;
@@ -850,6 +854,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
                return -EINVAL;
 
        pEnd = to_musb_ep(ep);
+       hw_ep = pEnd->hw_ep;
+       regs = hw_ep->regs;
        pThis = pEnd->pThis;
        pBase = pThis->pRegs;
        bEnd = pEnd->bEndNumber;
@@ -879,11 +885,11 @@ static int musb_gadget_enable(struct usb_ep *ep,
        if (desc->bEndpointAddress & USB_DIR_IN) {
                u16 wIntrTxE = musb_readw(pBase, MGC_O_HDRC_INTRTXE);
 
-               if (pEnd->hw_ep->bIsSharedFifo)
+               if (hw_ep->bIsSharedFifo)
                        pEnd->is_in = 1;
                if (!pEnd->is_in)
                        goto fail;
-               if (tmp > pEnd->hw_ep->wMaxPacketSizeTx)
+               if (tmp > hw_ep->wMaxPacketSizeTx)
                        goto fail;
 
                wIntrTxE |= (1 << bEnd);
@@ -892,25 +898,28 @@ static int musb_gadget_enable(struct usb_ep *ep,
                /* REVISIT if can_bulk_split(), use by updating "tmp";
                 * likewise high bandwidth periodic tx
                 */
-               MGC_WriteCsr16(pBase, MGC_O_HDRC_TXMAXP, bEnd, tmp);
+               musb_writew(regs, MGC_O_HDRC_TXMAXP, tmp);
 
-               csr = MGC_M_TXCSR_MODE | MGC_M_TXCSR_CLRDATATOG
-                               | MGC_M_TXCSR_FLUSHFIFO;
+               csr = MGC_M_TXCSR_MODE | MGC_M_TXCSR_CLRDATATOG;
+               if (musb_readw(regs, MGC_O_HDRC_TXCSR)
+                               & MGC_M_TXCSR_FIFONOTEMPTY)
+                       csr |= MGC_M_TXCSR_FLUSHFIFO;
                if (pEnd->type == USB_ENDPOINT_XFER_ISOC)
                        csr |= MGC_M_TXCSR_P_ISO;
 
                /* set twice in case of double buffering */
-               MGC_WriteCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd, csr);
-               MGC_WriteCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd, csr);
+               musb_writew(regs, MGC_O_HDRC_TXCSR, csr);
+               /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+               musb_writew(regs, MGC_O_HDRC_TXCSR, csr);
 
        } else {
                u16 wIntrRxE = musb_readw(pBase, MGC_O_HDRC_INTRRXE);
 
-               if (pEnd->hw_ep->bIsSharedFifo)
+               if (hw_ep->bIsSharedFifo)
                        pEnd->is_in = 0;
                if (pEnd->is_in)
                        goto fail;
-               if (tmp > pEnd->hw_ep->wMaxPacketSizeRx)
+               if (tmp > hw_ep->wMaxPacketSizeRx)
                        goto fail;
 
                wIntrRxE |= (1 << bEnd);
@@ -922,7 +931,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
                MGC_WriteCsr16(pBase, MGC_O_HDRC_RXMAXP, bEnd, tmp);
 
                /* force shared fifo to OUT-only mode */
-               if (pEnd->hw_ep->bIsSharedFifo) {
+               if (hw_ep->bIsSharedFifo) {
                        csr = musb_readw(pBase, MGC_O_HDRC_TXCSR);
                        csr &= ~(MGC_M_TXCSR_MODE | MGC_M_TXCSR_TXPKTRDY);
                        MGC_WriteCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd, csr);
@@ -945,7 +954,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
        if (is_dma_capable() && pThis->pDmaController) {
                struct dma_controller   *c = pThis->pDmaController;
 
-               pEnd->dma = c->channel_alloc(c, pEnd->hw_ep,
+               pEnd->dma = c->channel_alloc(c, hw_ep,
                                (desc->bEndpointAddress & USB_DIR_IN));
        } else
                pEnd->dma = NULL;
@@ -1292,9 +1301,10 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value)
        DBG(2, "%s: %s stall\n", ep->name, value ? "set" : "clear");
        if (pEnd->is_in) {
                wCsr = MGC_ReadCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd);
+               if (wCsr & MGC_M_TXCSR_FIFONOTEMPTY)
+                       wCsr |= MGC_M_TXCSR_FLUSHFIFO;
                wCsr |= MGC_M_TXCSR_P_WZC_BITS
-                       | MGC_M_TXCSR_CLRDATATOG
-                       | MGC_M_TXCSR_FLUSHFIFO;
+                       | MGC_M_TXCSR_CLRDATATOG;
                if (value)
                        wCsr |= MGC_M_TXCSR_P_SENDSTALL;
                else
@@ -1371,9 +1381,12 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
 
        if (musb_ep->is_in) {
                wCsr = MGC_ReadCsr16(mbase, MGC_O_HDRC_TXCSR, nEnd);
-               wCsr |= MGC_M_TXCSR_FLUSHFIFO | MGC_M_TXCSR_P_WZC_BITS;
-               MGC_WriteCsr16(mbase, MGC_O_HDRC_TXCSR, nEnd, wCsr);
-               MGC_WriteCsr16(mbase, MGC_O_HDRC_TXCSR, nEnd, wCsr);
+               if (wCsr & MGC_M_TXCSR_FIFONOTEMPTY) {
+                       wCsr |= MGC_M_TXCSR_FLUSHFIFO | MGC_M_TXCSR_P_WZC_BITS;
+                       MGC_WriteCsr16(mbase, MGC_O_HDRC_TXCSR, nEnd, wCsr);
+                       /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+                       MGC_WriteCsr16(mbase, MGC_O_HDRC_TXCSR, nEnd, wCsr);
+               }
        } else {
                wCsr = MGC_ReadCsr16(mbase, MGC_O_HDRC_RXCSR, nEnd);
                wCsr |= MGC_M_RXCSR_FLUSHFIFO | MGC_M_RXCSR_P_WZC_BITS;
@@ -1413,17 +1426,21 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
 {
        struct musb     *musb = gadget_to_musb(gadget);
        unsigned long   flags;
-       int             status = 0;
+       int             status = -EINVAL;
        u8              power;
 
        spin_lock_irqsave(&musb->Lock, flags);
 
+       /* fail if we're not suspended */
+       power = musb_readb(musb->pRegs, MGC_O_HDRC_POWER);
+       if (!(power & MGC_M_POWER_SUSPENDM))
+               goto done;
+
        switch (musb->xceiv.state) {
        case OTG_STATE_B_PERIPHERAL:
-               /* FIXME if not suspended, fail */
                if (musb->bMayWakeup)
                        break;
-               goto fail;
+               goto done;
        case OTG_STATE_B_IDLE:
                /* REVISIT we might be able to do SRP even without OTG,
                 * though Linux doesn't yet expose that capability
@@ -1434,12 +1451,10 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
                }
                /* FALLTHROUGH */
        default:
-fail:
-               status = -EINVAL;
                goto done;
        }
 
-       power = musb_readb(musb->pRegs, MGC_O_HDRC_POWER);
+       status = 0;
        power |= MGC_M_POWER_RESUME;
        musb_writeb(musb->pRegs, MGC_O_HDRC_POWER, power);
 
index d10dad91523b76222ed7b0bd212271fd5c1c2990..6cf568058d10b473d4ee8409771d0ddadafb568a 100644 (file)
@@ -717,7 +717,11 @@ static void musb_ep_program(struct musb *pThis, u8 bEnd,
                if (bEnd) {
                        u16     csr = wCsr;
 
+                       /* ASSERT:  TXCSR_DMAENAB was already cleared */
+
                        /* flush all old state, set default */
+                       if (csr & MGC_M_TXCSR_FIFONOTEMPTY)
+                               csr |= MGC_M_TXCSR_FLUSHFIFO;
                        csr &= ~(MGC_M_TXCSR_H_NAKTIMEOUT
                                        | MGC_M_TXCSR_DMAMODE
                                        | MGC_M_TXCSR_FRCDATATOG
@@ -727,8 +731,7 @@ static void musb_ep_program(struct musb *pThis, u8 bEnd,
                                        | MGC_M_TXCSR_FIFONOTEMPTY
                                        | MGC_M_TXCSR_TXPKTRDY
                                        );
-                       csr |= MGC_M_TXCSR_FLUSHFIFO
-                                       | MGC_M_TXCSR_MODE;
+                       csr |= MGC_M_TXCSR_MODE;
 
                        if (qh->type == USB_ENDPOINT_XFER_ISOC)
                                csr |= MGC_M_TXCSR_ISO;
@@ -742,6 +745,7 @@ static void musb_ep_program(struct musb *pThis, u8 bEnd,
                        /* twice in case of double packet buffering */
                        MGC_WriteCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd,
                                        csr);
+                       /* REVISIT may need to clear FLUSHFIFO ... */
                        MGC_WriteCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd,
                                        csr);
                        wCsr = MGC_ReadCsr16(pBase, MGC_O_HDRC_TXCSR,
@@ -765,6 +769,7 @@ static void musb_ep_program(struct musb *pThis, u8 bEnd,
                        musb_writeb(pBase,
                                MGC_BUSCTL_OFFSET(bEnd, MGC_O_HDRC_TXHUBPORT),
                                qh->h_port_reg);
+/* FIXME if !bEnd, do the same for RX ... */
                } else
                        musb_writeb(pBase, MGC_O_HDRC_FADDR, qh->addr_reg);
 
@@ -884,6 +889,8 @@ static void musb_ep_program(struct musb *pThis, u8 bEnd,
                }
 #endif
                if (wLoadCount) {
+                       /* ASSERT:  TXCSR_DMAENAB was already cleared */
+
                        /* PIO to load FIFO */
                        qh->segsize = wLoadCount;
                        musb_write_fifo(pEnd, wLoadCount, pBuffer);
@@ -1223,13 +1230,15 @@ void musb_host_tx(struct musb *pThis, u8 bEnd)
 
        /* check for errors */
        if (wTxCsrVal & MGC_M_TXCSR_H_RXSTALL) {
+               /* dma was disabled, fifo flushed */
                DBG(3, "TX end %d stall\n", bEnd);
 
                /* stall; record URB status */
                status = -EPIPE;
 
        } else if (wTxCsrVal & MGC_M_TXCSR_H_ERROR) {
-               DBG(3, "TX data error on ep=%d\n", bEnd);
+               /* (NON-ISO) dma was disabled, fifo flushed */
+               DBG(3, "TX 3strikes on ep=%d\n", bEnd);
 
                status = -ETIMEDOUT;
 
@@ -1260,6 +1269,8 @@ void musb_host_tx(struct musb *pThis, u8 bEnd)
                 * usb core; the dma engine should already be stopped.
                 */
 // SCRUB (TX)
+               if (wTxCsrVal & MGC_M_TXCSR_FIFONOTEMPTY)
+                       wTxCsrVal |= MGC_M_TXCSR_FLUSHFIFO;
                wTxCsrVal &= ~(MGC_M_TXCSR_FIFONOTEMPTY
                                | MGC_M_TXCSR_AUTOSET
                                | MGC_M_TXCSR_DMAENAB
@@ -1267,10 +1278,10 @@ void musb_host_tx(struct musb *pThis, u8 bEnd)
                                | MGC_M_TXCSR_H_RXSTALL
                                | MGC_M_TXCSR_H_NAKTIMEOUT
                                );
-               wTxCsrVal |= MGC_M_TXCSR_FLUSHFIFO;
 
                MGC_SelectEnd(pBase, bEnd);
                MGC_WriteCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd, wTxCsrVal);
+               /* REVISIT may need to clear FLUSHFIFO ... */
                MGC_WriteCsr16(pBase, MGC_O_HDRC_TXCSR, bEnd, wTxCsrVal);
                MGC_WriteCsr8(pBase, MGC_O_HDRC_TXINTERVAL, bEnd, 0);
 
@@ -1977,6 +1988,8 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
        } else {
 // SCRUB (TX)
                csr = MGC_ReadCsr16(regs, MGC_O_HDRC_TXCSR, hw_end);
+               if (csr & MGC_M_TXCSR_FIFONOTEMPTY)
+                       csr |= MGC_M_TXCSR_FLUSHFIFO;
                csr &= ~( MGC_M_TXCSR_AUTOSET
                        | MGC_M_TXCSR_DMAENAB
                        | MGC_M_TXCSR_H_RXSTALL
@@ -1984,8 +1997,8 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in)
                        | MGC_M_TXCSR_H_ERROR
                        | MGC_M_TXCSR_FIFONOTEMPTY
                        );
-               csr |= MGC_M_TXCSR_FLUSHFIFO;
                MGC_WriteCsr16(regs, MGC_O_HDRC_TXCSR, 0, csr);
+               /* REVISIT may need to clear FLUSHFIFO ... */
                MGC_WriteCsr16(regs, MGC_O_HDRC_TXCSR, 0, csr);
                /* flush cpu writebuffer */
                csr = MGC_ReadCsr16(regs, MGC_O_HDRC_TXCSR, hw_end);
index 188a7f07541d75278c77809b5c6e01df142e8991..59fbbd7d486fe18d042dedb877db4476b7739478 100644 (file)
@@ -71,8 +71,6 @@
 /* Additional Control Registers */
 
 #define MGC_O_HDRC_DEVCTL      0x60    /* 8 bit */
-// vctrl/vstatus:  optional vendor utmi+phy register at 0x68
-#define MGC_O_HDRC_HWVERS      0x6C    /* 8 bit */
 
 /* These are always controlled through the INDEX register */
 #define MGC_O_HDRC_TXFIFOSZ    0x62    /* 8-bit (see masks) */
 #define MGC_O_HDRC_TXFIFOADD   0x64    /* 16-bit offset shifted right 3 */
 #define MGC_O_HDRC_RXFIFOADD   0x66    /* 16-bit offset shifted right 3 */
 
+// vctrl/vstatus:  optional vendor utmi+phy register at 0x68
+#define MGC_O_HDRC_HWVERS      0x6C    /* 8 bit */
+
+#define MGC_O_HDRC_EPINFO      0x78    /* 8 bit */
+#define MGC_O_HDRC_RAMINFO     0x79    /* 8 bit */
+#define MGC_O_HDRC_LINKINFO    0x7a    /* 8 bit */
+#define MGC_O_HDRC_VPLEN       0x7b    /* 8 bit */
+#define MGC_O_HDRC_HS_EOF1     0x7c    /* 8 bit */
+#define MGC_O_HDRC_FS_EOF1     0x7d    /* 8 bit */
+#define MGC_O_HDRC_LS_EOF1     0x7e    /* 8 bit */
+
 /* offsets to endpoint registers */
 #define MGC_O_HDRC_TXMAXP      0x00
 #define MGC_O_HDRC_TXCSR       0x02
 #include "tusb6010.h"          /* needed "only" for TUSB_EP0_CONF */
 #endif
 
-/* "bus control" registers */
+/* "bus control"/target registers, for host side multipoint (external hubs) */
 #define MGC_O_HDRC_TXFUNCADDR  0x00
 #define MGC_O_HDRC_TXHUBADDR   0x02
 #define MGC_O_HDRC_TXHUBPORT   0x03
 #define MGC_M_INTR_DISCONNECT 0x20
 #define MGC_M_INTR_SESSREQ    0x40
 #define MGC_M_INTR_VBUSERROR  0x80     /* FOR SESSION END */
-#define MGC_M_INTR_EP0      0x01       /* FOR EP0 INTERRUPT */
 
 /* DEVCTL */
 #define MGC_M_DEVCTL_BDEVICE    0x80
 #define MGC_M_CSR0_P_SENTSTALL    0x0004
 
 /* CSR0 in Host mode */
+#define MGC_M_CSR0_H_DIS_PING  0x0800
 #define MGC_M_CSR0_H_WR_DATATOGGLE   0x0400    /* set to allow setting: */
 #define MGC_M_CSR0_H_DATATOGGLE            0x0200      /* data toggle control */
 #define MGC_M_CSR0_H_NAKTIMEOUT   0x0080
 #define MGC_TYPE_SPEED_HIGH    1
 #define MGC_TYPE_SPEED_FULL    2
 #define MGC_TYPE_SPEED_LOW     3
-#define MGC_M_TYPE_PROTO       0x30
+#define MGC_M_TYPE_PROTO       0x30    /* implicitly zero for ep0 */
 #define MGC_S_TYPE_PROTO       4
-#define MGC_M_TYPE_REMOTE_END  0xf
+#define MGC_M_TYPE_REMOTE_END  0xf     /* implicitly zero for ep0 */
 
 /* CONFIGDATA */
 
 #define MGC_M_RXCSR_AUTOCLEAR     0x8000
 #define MGC_M_RXCSR_DMAENAB       0x2000
 #define MGC_M_RXCSR_DISNYET       0x1000
+#define MGC_M_RXCSR_PID_ERR       0x1000
 #define MGC_M_RXCSR_DMAMODE       0x0800
 #define MGC_M_RXCSR_INCOMPRX      0x0100
 #define MGC_M_RXCSR_CLRDATATOG    0x0080
index 9ba7b230ca570a8970232ac6b22ac9b9eed126a5..77fd3a31b1703860102344592d76390d052ee295 100644 (file)
@@ -387,7 +387,10 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB,
 
                if (devctl & MGC_M_DEVCTL_HM) {
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
-                       /* REVISIT:  this is where SRP kicks in, yes? */
+                       /* REVISIT:  this is where SRP kicks in, yes?
+                        * host responsibility should be to CLEAR the
+                        * resume signaling after 50 msec ...
+                        */
                        MUSB_HST_MODE(pThis);   /* unnecessary */
                        power &= ~MGC_M_POWER_SUSPENDM;
                        musb_writeb(pBase, MGC_O_HDRC_POWER,
index 0aa87bb34737d7d10f915504386085ed786e68fe..b3300705dc7f79daab300f7c3a1d9400d3dcaf60 100644 (file)
@@ -60,7 +60,6 @@ static void musb_port_suspend(struct musb *musb, u8 bSuspend)
                musb->port1_status |= USB_PORT_STAT_SUSPEND;
        } else if (power & MGC_M_POWER_SUSPENDM) {
                DBG(3, "Root port resumed\n");
-               power &= ~(MGC_M_POWER_SUSPENDM | MGC_M_POWER_RESUME);
                musb_writeb(pBase, MGC_O_HDRC_POWER,
                                power | MGC_M_POWER_RESUME);