From patchwork Thu Dec 3 13:56:08 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: riku.voipio@nokia.com X-Patchwork-Id: 40262 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id AA2DEB7082 for ; Fri, 4 Dec 2009 09:18:08 +1100 (EST) Received: from localhost ([127.0.0.1]:46418 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NGJzx-0002Sz-1N for incoming@patchwork.ozlabs.org; Thu, 03 Dec 2009 17:18:05 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NGCB0-0001OU-K1 for qemu-devel@nongnu.org; Thu, 03 Dec 2009 08:56:58 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NGCAv-0001KM-9D for qemu-devel@nongnu.org; Thu, 03 Dec 2009 08:56:58 -0500 Received: from [199.232.76.173] (port=56417 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NGCAu-0001K5-Uf for qemu-devel@nongnu.org; Thu, 03 Dec 2009 08:56:52 -0500 Received: from smtp.nokia.com ([192.100.105.134]:42975 helo=mgw-mx09.nokia.com) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NGCAu-0008GK-7W for qemu-devel@nongnu.org; Thu, 03 Dec 2009 08:56:52 -0500 Received: from esebh106.NOE.Nokia.com (esebh106.ntc.nokia.com [172.21.138.213]) by mgw-mx09.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nB3DuY5N023940 for ; Thu, 3 Dec 2009 07:56:50 -0600 Received: from esebh102.NOE.Nokia.com ([172.21.138.183]) by esebh106.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Thu, 3 Dec 2009 15:56:48 +0200 Received: from mgw-da02.ext.nokia.com ([147.243.128.26]) by esebh102.NOE.Nokia.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Thu, 3 Dec 2009 15:56:48 +0200 Received: from localhost.localdomain (esdhcp041213.research.nokia.com [172.21.41.213]) by mgw-da02.ext.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nB3DuZpA027643; Thu, 3 Dec 2009 15:56:45 +0200 From: riku.voipio@nokia.com To: qemu-devel@nongnu.org Date: Thu, 3 Dec 2009 15:56:08 +0200 Message-Id: <9222b6e065e2c651868d64d35bbd25c0e217334b.1259836046.git.riku.voipio@nokia.com> X-Mailer: git-send-email 1.6.3.3 In-Reply-To: References: In-Reply-To: References: X-OriginalArrivalTime: 03 Dec 2009 13:56:48.0709 (UTC) FILETIME=[752C3F50:01CA7420] X-Nokia-AV: Clean X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 1) X-Mailman-Approved-At: Thu, 03 Dec 2009 17:06:16 -0500 Cc: Riku Voipio Subject: [Qemu-devel] [PATCH 7/7] usb-musb: convert fifo to 8bit and add more registers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Riku Voipio Convert musb fifo to 8bit to allow 8/16/32bit access 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. While at it, add multiple missing register definitions and and cleanup debug prints. Signed-off-by: Riku Voipio --- hw/usb-musb.c | 164 +++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 107 insertions(+), 57 deletions(-) diff --git a/hw/usb-musb.c b/hw/usb-musb.c index 09ec5a1..7f15842 100644 --- a/hw/usb-musb.c +++ b/hw/usb-musb.c @@ -24,6 +24,7 @@ #include "qemu-timer.h" #include "usb.h" #include "irq.h" +#include "hw.h" /* Common USB registers */ #define MUSB_HDRC_FADDR 0x00 /* 8-bit */ @@ -248,6 +249,16 @@ #define MGC_M_ULPI_REGCTL_COMPLETE 0x02 #define MGC_M_ULPI_REGCTL_REG 0x01 +/* #define MUSB_DEBUG */ + +#ifdef MUSB_DEBUG +#define TRACE(fmt,...) fprintf(stderr, "%s@%d: " fmt "\n", __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) +#else +#define TRACE(...) +#endif + + static void musb_attach(USBPort *port, USBDevice *dev); typedef struct { @@ -263,7 +274,7 @@ typedef struct { 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]; @@ -299,7 +310,7 @@ struct MUSBState { int setup_len; int session; - uint32_t buf[0x2000]; + uint8_t buf[0x8000]; /* Duplicating the world since 2008!... probably we should have 32 * logical, single endpoints instead. */ @@ -774,7 +785,7 @@ static void musb_tx_rdy(MUSBState *s, int epnum) MUSBEndPoint *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; @@ -789,18 +800,18 @@ static void musb_tx_rdy(MUSBState *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)) { pid = USB_TOKEN_SETUP; - if (total != 8) - printf("%s: illegal SETUPPKT length of %i bytes\n", - __FUNCTION__, total); + if (total != 8) { + TRACE("illegal SETUPPKT length of %i bytes", total); + } /* Controller should retry SETUP packets three times on errors * but it doesn't make sense for us to do that. */ } @@ -817,12 +828,13 @@ static void musb_rx_req(MUSBState *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; @@ -872,6 +884,36 @@ static void musb_rx_req(MUSBState *s, int epnum) total, musb_rx_packet_complete, 1); } +static uint8_t musb_read_fifo(MUSBEndPoint *ep) +{ + uint8_t value; + if (ep->fifolen[1] >= 64) { + /* We have a FIFO underrun */ + TRACE("EP%d FIFO is now empty, stop reading", 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(MUSBEndPoint *ep, uint8_t value) +{ + TRACE("EP%d = %02x", ep->epnum, value); + if (ep->fifolen[0] >= 64) { + /* We have a FIFO overrun */ + TRACE("EP%d FIFO exceeded 64 bytes, stop feeding data", 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(MUSBEndPoint *ep, int dir) { if (ep->intv_timer[dir]) @@ -895,7 +937,7 @@ static uint8_t musb_busctl_readb(void *opaque, int ep, int addr) return s->ep[ep].hport[1]; default: - printf("%s: unknown register at %02x\n", __FUNCTION__, addr); + TRACE("unknown register 0x%02x", addr); return 0x00; }; } @@ -905,6 +947,12 @@ static void musb_busctl_writeb(void *opaque, int ep, int addr, uint8_t value) MUSBState *s = (MUSBState *) opaque; switch (addr) { + case MUSB_HDRC_TXFUNCADDR: + s->ep[ep].faddr[0] = value; + break; + case MUSB_HDRC_RXFUNCADDR: + s->ep[ep].faddr[1] = value; + break; case MUSB_HDRC_TXHUBADDR: s->ep[ep].haddr[0] = value; break; @@ -919,7 +967,8 @@ static void musb_busctl_writeb(void *opaque, int ep, int addr, uint8_t value) break; default: - printf("%s: unknown register at %02x\n", __FUNCTION__, addr); + TRACE("unknown register 0x%02x", addr); + break; }; } @@ -975,9 +1024,11 @@ static uint8_t musb_ep_readb(void *opaque, int ep, int addr) return 0x00; case MUSB_HDRC_FIFOSIZE: return ep ? s->ep[ep].fifosize : s->ep[ep].config; + case MUSB_HDRC_RXCOUNT: + return s->ep[ep].rxcount; default: - printf("%s: unknown register at %02x\n", __FUNCTION__, addr); + TRACE("unknown register 0x%02x", addr); return 0x00; }; } @@ -1004,13 +1055,12 @@ static void musb_ep_writeb(void *opaque, int ep, int addr, uint8_t value) case (MUSB_HDRC_FIFOSIZE & ~1): break; case MUSB_HDRC_FIFOSIZE: - printf("%s: somebody messes with fifosize (now %i bytes)\n", - __FUNCTION__, value); + TRACE("somebody messes with fifosize (now %i bytes)", value); s->ep[ep].fifosize = value; break; - default: - printf("%s: unknown register at %02x\n", __FUNCTION__, addr); + TRACE("unknown register 0x%02x", addr); + break; }; } @@ -1194,8 +1244,12 @@ 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); + TRACE("unknown register 0x%02x", (int) addr); return 0x00; }; } @@ -1276,8 +1330,14 @@ 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); + TRACE("unknown register 0x%02x", (int) addr); + break; }; } @@ -1326,6 +1386,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); }; @@ -1353,12 +1417,12 @@ 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 ); 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); break; case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf): @@ -1375,6 +1439,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); @@ -1384,28 +1454,17 @@ 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) { MUSBState *s = (MUSBState *) opaque; - MUSBEndPoint *ep; - int epnum; + 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); + TRACE("unknown register 0x%02x", (int) addr); return 0x00000000; }; } @@ -1413,28 +1472,19 @@ 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) { MUSBState *s = (MUSBState *) opaque; - MUSBEndPoint *ep; - int epnum; + 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[0] >= 16) { - /* We have a FIFO overrun */ - printf("%s: EP%i FIFO exceeded 64 bytes, stop feeding data\n", - __FUNCTION__, epnum); + 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; - } - - ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value; - if (epnum) - ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY; - break; - default: - printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr); + TRACE("unknown register 0x%02x", (int) addr); + break; }; }