Convert musb fifo to 8bit to allow 8/16/32bit access
authorRiku Voipio <riku.voipio@nokia.com>
Tue, 17 Mar 2009 15:19:55 +0000 (17:19 +0200)
committerRiku Voipio <riku.voipio@nokia.com>
Thu, 19 Mar 2009 14:25:34 +0000 (16:25 +0200)
MUSB allows reading and writing to the fifo in 32/16/8 bit
width. The Linux kernel does this sometimes, most usually at
the end of writing the packet to allow packet to end at a
odd bytecount.

Convert the fifo to 8bit allows removing lots of shifts
which shows that the fifo is more natural as 8bit.

hw/usb-musb.c

index 8eba6d1..bb36be7 100644 (file)
@@ -279,7 +279,7 @@ struct musb_s {
     int setup_len;
     int session;
 
-    uint32_t buf[0x2000];
+    uint8_t buf[0x8000];
 
     struct musb_ep_s {
         uint16_t faddr[2];
@@ -294,7 +294,7 @@ struct musb_s {
         uint8_t fifosize;
         int timeout[2];        /* Always in microframes */
 
-        uint32_t *buf[2];
+        uint8_t *buf[2];
         int fifolen[2];
         int fifostart[2];
         int fifoaddr[2];
@@ -780,7 +780,7 @@ static void musb_tx_rdy(struct musb_s *s, int epnum)
     struct musb_ep_s *ep = s->ep + epnum;
     int pid;
     int total, valid = 0;
-
+    TRACE("start %d, len %d",  ep->fifostart[0], ep->fifolen[0] );
     ep->fifostart[0] += ep->fifolen[0];
     ep->fifolen[0] = 0;
 
@@ -795,11 +795,11 @@ static void musb_tx_rdy(struct musb_s *s, int epnum)
     }
 
     /* If the packet is not fully ready yet, wait for a next segment.  */
-    if (epnum && (ep->fifostart[0] << 2) < total)
+    if (epnum && (ep->fifostart[0]) < total)
         return;
 
     if (!valid)
-        total = ep->fifostart[0] << 2;
+        total = ep->fifostart[0];
 
     pid = USB_TOKEN_OUT;
     if (!epnum && (ep->csr[0] & MGC_M_CSR0_H_SETUPPKT)) {
@@ -823,12 +823,13 @@ static void musb_rx_req(struct musb_s *s, int epnum)
     /* If we already have a packet, which didn't fit into the
      * 64 bytes of the FIFO, only move the FIFO start and return. (Obsolete) */
     if (ep->packey[1].pid == USB_TOKEN_IN && ep->status[1] >= 0 &&
-                    (ep->fifostart[1] << 2) + ep->rxcount <
+                    (ep->fifostart[1]) + ep->rxcount <
                     ep->packey[1].len) {
-        ep->fifostart[1] += ep->rxcount >> 2;
+        TRACE("0x%08x, %d",  ep->fifostart[1], ep->rxcount );
+        ep->fifostart[1] += ep->rxcount;
         ep->fifolen[1] = 0;
 
-        ep->rxcount = MIN(ep->packey[0].len - (ep->fifostart[1] << 2),
+        ep->rxcount = MIN(ep->packey[0].len - (ep->fifostart[1]),
                         ep->maxp[1]);
 
         ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
@@ -878,6 +879,38 @@ static void musb_rx_req(struct musb_s *s, int epnum)
                     total, musb_rx_packet_complete, 1);
 }
 
+static uint8_t musb_read_fifo(struct musb_ep_s *ep)
+{
+    uint8_t value;
+    if (ep->fifolen[1] >= 64) {
+        /* We have a FIFO underrun */
+        printf("%s: EP%d FIFO is now empty, stop reading\n",
+                __FUNCTION__, ep->epnum);
+        return 0x00000000;
+    }
+    /* In DMA mode clear RXPKTRDY and set REQPKT automatically
+     * (if AUTOREQ is set) */
+
+    ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;
+    value=ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];
+    TRACE("EP%d 0x%02x, %d", ep->epnum, value, ep->fifolen[1] );
+    return value;
+}
+
+static void musb_write_fifo(struct musb_ep_s *ep, uint8_t value)
+{
+    TRACE("EP%d = %02x", ep->epnum, value);
+    if (ep->fifolen[0] >= 64) {
+        /* We have a FIFO overrun */
+        printf("%s: EP%d FIFO exceeded 64 bytes, stop feeding data\n",
+                __FUNCTION__, ep->epnum);
+        return;
+     }
+
+     ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value;
+     ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY;
+}
+
 static void musb_ep_frame_cancel(struct musb_ep_s *ep, int dir)
 {
     if (ep->intv_timer[dir])
@@ -888,7 +921,7 @@ static void musb_ep_frame_cancel(struct musb_ep_s *ep, int dir)
 static uint8_t musb_busctl_readb(void *opaque, int ep, int addr)
 {
     struct musb_s *s = (struct musb_s *) opaque;
-    TRACE("ADDR = 0x%08x", addr);
+//    TRACE("ADDR = 0x%08x", addr);
 
     switch (addr) {
     /* For USB2.0 HS hubs only */
@@ -1161,7 +1194,7 @@ static uint32_t musb_readb(void *opaque, target_phys_addr_t addr)
     struct musb_s *s = (struct musb_s *) opaque;
     int ep, i;
     uint8_t ret;
-    TRACE("ADDR = 0x%08x", addr);
+//    TRACE("ADDR = 0x%08x", addr);
 
     switch (addr) {
     case MUSB_HDRC_FADDR:
@@ -1209,6 +1242,10 @@ static uint32_t musb_readb(void *opaque, target_phys_addr_t addr)
         ep = (addr >> 4) & 0xf;
         return musb_ep_readb(s, ep, addr & 0xf);
 
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        return musb_read_fifo(s->ep + ep);
+
     default:
         printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);
         return 0x00;
@@ -1219,7 +1256,7 @@ static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 {
     struct musb_s *s = (struct musb_s *) opaque;
     int ep;
-    TRACE("ADDR = 0x%08x = %08x", addr, value);
+//    TRACE("ADDR = 0x%08x = %08x", addr, value);
 
     switch (addr) {
     case MUSB_HDRC_FADDR:
@@ -1292,6 +1329,11 @@ static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
         musb_ep_writeb(s, ep, addr & 0xf, value);
         break;
 
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        musb_write_fifo(s->ep + ep, value & 0xff);
+        break;
+
     default:
         printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);
     };
@@ -1302,7 +1344,7 @@ static uint32_t musb_readh(void *opaque, target_phys_addr_t addr)
     struct musb_s *s = (struct musb_s *) opaque;
     int ep, i;
     uint16_t ret;
-    TRACE("ADDR = 0x%08x", addr);
+//    TRACE("ADDR = 0x%08x", addr);
 
     switch (addr) {
     case MUSB_HDRC_INTRTX:
@@ -1343,6 +1385,10 @@ static uint32_t musb_readh(void *opaque, target_phys_addr_t addr)
         ep = (addr >> 4) & 0xf;
         return musb_ep_readh(s, ep, addr & 0xf);
 
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        return (musb_read_fifo(s->ep + ep) | musb_read_fifo(s->ep + ep) << 8);
+
     default:
         return musb_readb(s, addr) | (musb_readb(s, addr | 1) << 8);
     };
@@ -1352,7 +1398,6 @@ static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
 {
     struct musb_s *s = (struct musb_s *) opaque;
     int ep;
-    TRACE("ADDR = 0x%08x = %08x", addr, value);
 
     switch (addr) {
     case MUSB_HDRC_INTRTXE:
@@ -1371,12 +1416,14 @@ static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
     case MUSB_HDRC_TXFIFOADDR:
         s->ep[s->idx].fifoaddr[0] = value;
         s->ep[s->idx].buf[0] =
-                s->buf + ((value << 1) & (sizeof(s->buf) / 4 - 1));
+                s->buf + ((value << 3) & 0x7ff );
+       TRACE("TXFIFOADDR = 0x%08x, BUF %08x", value, s->ep[s->idx].buf[0]);
         break;
     case MUSB_HDRC_RXFIFOADDR:
         s->ep[s->idx].fifoaddr[1] = value;
         s->ep[s->idx].buf[1] =
-                s->buf + ((value << 1) & (sizeof(s->buf) / 4 - 1));
+                s->buf + ((value << 3) & 0x7ff);
+       TRACE("RXFIFOADDR = 0x%08x, BUF %08x", value, s->ep[s->idx].buf[1]);
         break;
 
     case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
@@ -1393,6 +1440,12 @@ static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
         musb_ep_writeh(s, ep, addr & 0xf, value);
         break;
 
+    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        musb_write_fifo(s->ep + ep, value & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 8) & 0xff);
+        break;
+
     default:
         musb_writeb(s, addr, value & 0xff);
         musb_writeb(s, addr | 1, value >> 8);
@@ -1402,27 +1455,15 @@ static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
 static uint32_t musb_readw(void *opaque, target_phys_addr_t addr)
 {
     struct musb_s *s = (struct musb_s *) opaque;
-    struct musb_ep_s *ep;
-    int epnum;
-    TRACE("ADDR = 0x%08x", addr);
+    int ep;
 
     switch (addr) {
     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        epnum = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        ep = s->ep + epnum;
-
-        if (ep->fifolen[1] >= 16) {
-            /* We have a FIFO underrun */
-            printf("%s: EP%i FIFO is now empty, stop reading\n",
-                            __FUNCTION__, epnum);
-            return 0x00000000;
-        }
-        /* In DMA mode clear RXPKTRDY and set REQPKT automatically
-         * (if AUTOREQ is set) */
-
-        ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;
-        return ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];
-
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        return ( musb_read_fifo(s->ep + ep)       |
+                 musb_read_fifo(s->ep + ep) << 8  |
+                 musb_read_fifo(s->ep + ep) << 16 |
+                 musb_read_fifo(s->ep + ep) << 24 );
     default:
         printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);
         return 0x00000000;
@@ -1432,27 +1473,17 @@ static uint32_t musb_readw(void *opaque, target_phys_addr_t addr)
 static void musb_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
 {
     struct musb_s *s = (struct musb_s *) opaque;
-    struct musb_ep_s *ep;
-    int epnum;
-    TRACE("ADDR = 0x%08x = %08x", addr, value);
+    int ep;
+//    TRACE("ADDR = 0x%08x = %08x", addr, value);
 
     switch (addr) {
     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        epnum = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        ep = s->ep + epnum;
-
-        if (ep->fifolen[0] >= 16) {
-            /* We have a FIFO overrun */
-            printf("%s: EP%i FIFO exceeded 64 bytes, stop feeding data\n",
-                            __FUNCTION__, epnum);
-            break;
-        }
-
-        ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value;
-        if (epnum)
-            ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY;
+        ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
+        musb_write_fifo(s->ep + ep, value & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 8 ) & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 16) & 0xff);
+        musb_write_fifo(s->ep + ep, (value >> 24) & 0xff);
         break;
-
     default:
         printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);
     };