Merge commit 'origin/master' into juha-devel
[qemu] / hw / usb-musb.c
index 788b5ee..7c06b9e 100644 (file)
@@ -32,8 +32,8 @@
 
 #define MUSB_HDRC_INTRTX       0x02    /* 16-bit */
 #define MUSB_HDRC_INTRRX       0x04
-#define MUSB_HDRC_INTRTXE      0x06  
-#define MUSB_HDRC_INTRRXE      0x08  
+#define MUSB_HDRC_INTRTXE      0x06
+#define MUSB_HDRC_INTRRXE      0x08
 #define MUSB_HDRC_INTRUSB      0x0a    /* 8 bit */
 #define MUSB_HDRC_INTRUSBE     0x0b    /* 8 bit */
 #define MUSB_HDRC_FRAME                0x0c    /* 16-bit */
  */
 
 /* POWER */
-#define MGC_M_POWER_ISOUPDATE          0x80 
+#define MGC_M_POWER_ISOUPDATE          0x80
 #define        MGC_M_POWER_SOFTCONN            0x40
 #define        MGC_M_POWER_HSENAB              0x20
 #define        MGC_M_POWER_HSMODE              0x10
 #define MGC_M_INTR_RESUME              0x02
 #define MGC_M_INTR_RESET               0x04
 #define MGC_M_INTR_BABBLE              0x04
-#define MGC_M_INTR_SOF                 0x08 
+#define MGC_M_INTR_SOF                 0x08
 #define MGC_M_INTR_CONNECT             0x10
 #define MGC_M_INTR_DISCONNECT          0x20
 #define MGC_M_INTR_SESSREQ             0x40
 #define MGC_M_INTR_EP0                 0x01    /* FOR EP0 INTERRUPT */
 
 /* DEVCTL */
-#define MGC_M_DEVCTL_BDEVICE           0x80   
+#define MGC_M_DEVCTL_BDEVICE           0x80
 #define MGC_M_DEVCTL_FSDEV             0x40
 #define MGC_M_DEVCTL_LSDEV             0x20
 #define MGC_M_DEVCTL_VBUS              0x18
@@ -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,13 +879,13 @@ static void musb_rx_req(struct musb_s *s, int epnum)
                     total, musb_rx_packet_complete, 1);
 }
 
-static uint32_t musb_read_fifo(struct musb_ep_s *ep)
+static uint8_t musb_read_fifo(struct musb_ep_s *ep)
 {
-    uint32_t value;
-    if (ep->fifolen[1] >= 16) {
+    uint8_t value;
+    if (ep->fifolen[1] >= 64) {
         /* We have a FIFO underrun */
-        printf("%s: EP FIFO is now empty, stop reading\n",
-                __FUNCTION__);
+        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
@@ -892,10 +893,24 @@ static uint32_t musb_read_fifo(struct musb_ep_s *ep)
 
     ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;
     value=ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];
-    TRACE("fifo_read 0x%08x, %d", value, 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])
@@ -906,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 */
@@ -1179,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:
@@ -1241,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:
@@ -1314,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);
     };
@@ -1324,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:
@@ -1367,7 +1387,7 @@ static uint32_t musb_readh(void *opaque, target_phys_addr_t addr)
 
     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
         ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        return musb_read_fifo(s->ep + ep);
+        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);
@@ -1378,7 +1398,7 @@ 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);
+    //TRACE("ADDR = 0x%08x = %08x", addr, value);
 
     switch (addr) {
     case MUSB_HDRC_INTRTXE:
@@ -1397,12 +1417,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):
@@ -1419,6 +1441,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);
@@ -1428,12 +1456,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;
-    int epnum;
+    int ep;
 
     switch (addr) {
     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
-        epnum = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
-        return musb_read_fifo(s->ep + epnum);
+        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;
@@ -1443,27 +1474,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);
     };