Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Sep 2012 19:15:29 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r240419 - head/sys/dev/usb/controller
Message-ID:  <201209121915.q8CJFTwk031651@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Wed Sep 12 19:15:29 2012
New Revision: 240419
URL: http://svn.freebsd.org/changeset/base/240419

Log:
  Fix TX FIFO sizes. Correct FIFO handling in Host mode.

Modified:
  head/sys/dev/usb/controller/dwc_otg.c
  head/sys/dev/usb/controller/dwc_otg.h

Modified: head/sys/dev/usb/controller/dwc_otg.c
==============================================================================
--- head/sys/dev/usb/controller/dwc_otg.c	Wed Sep 12 18:18:14 2012	(r240418)
+++ head/sys/dev/usb/controller/dwc_otg.c	Wed Sep 12 19:15:29 2012	(r240419)
@@ -211,24 +211,34 @@ dwc_otg_init_fifo(struct dwc_otg_softc *
 		return (EINVAL);
 	}
 
-	DWC_OTG_WRITE_4(sc, DOTG_GNPTXFSIZ, (0x10 << 16) | (tx_start / 4));
-	fifo_size -= 0x40;
-	tx_start += 0x40;
-
-	/* setup control endpoint profile */
-	sc->sc_hw_ep_profile[0].usb = dwc_otg_ep_profile[0];
-
 	if (mode == DWC_MODE_HOST) {
 
 		/* reset active endpoints */
 		sc->sc_active_rx_ep = 0;
 
+		fifo_size /= 2;
+
+		DWC_OTG_WRITE_4(sc, DOTG_GNPTXFSIZ,
+		    ((fifo_size / 4) << 16) |
+		    (tx_start / 4));
+
+		tx_start += fifo_size;
+
 		DWC_OTG_WRITE_4(sc, DOTG_HPTXFSIZ,
 		    ((fifo_size / 4) << 16) |
 		    (tx_start / 4));
 	}
+
 	if (mode == DWC_MODE_DEVICE) {
 
+	    DWC_OTG_WRITE_4(sc, DOTG_GNPTXFSIZ,
+	        (0x10 << 16) | (tx_start / 4));
+	    fifo_size -= 0x40;
+	    tx_start += 0x40;
+
+	    /* setup control endpoint profile */
+	    sc->sc_hw_ep_profile[0].usb = dwc_otg_ep_profile[0];
+
 	    /* reset active endpoints */
 	    sc->sc_active_rx_ep = 1;
 
@@ -521,18 +531,11 @@ dwc_otg_host_channel_alloc(struct dwc_ot
 			/* enable interrupts */
 			DWC_OTG_WRITE_4(sc, DOTG_HCINTMSK(x),
 			    HCINT_STALL | HCINT_BBLERR |
-			    HCINT_AHBERR | HCINT_CHHLTD |
-			    HCINT_XACTERR | HCINT_XFERCOMPL |
-			    HCINT_NAK | HCINT_NYET);
+			    HCINT_AHBERR | HCINT_XACTERR |
+			    HCINT_XFERCOMPL | HCINT_NAK);
 
 			DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(x), td->hcsplt);
 			DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(x), 0);
-			DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(x), 0);
-
-			/* reset TX FIFO */
-			DWC_OTG_WRITE_4(sc, DOTG_GRSTCTL,
-			    GRSTCTL_TXFIFO(x) |
-			    GRSTCTL_TXFFLSH);
 
 			/* set channel */
 			td->channel = x;
@@ -581,8 +584,7 @@ dwc_otg_host_setup_tx(struct dwc_otg_td 
 		return (0);		/* complete */
 	}
 
-	if (temp & (HCINT_BBLERR |
-	    HCINT_AHBERR | HCINT_CHHLTD | HCINT_XACTERR)) {
+	if (temp & (HCINT_BBLERR | HCINT_AHBERR | HCINT_XACTERR)) {
 		td->error_any = 1;
 		return (0);		/* complete */
 	}
@@ -783,7 +785,6 @@ dwc_otg_host_data_rx(struct dwc_otg_td *
 	struct dwc_otg_softc *sc;
 	uint32_t temp;
 	uint16_t count;
-	uint8_t got_short;
 	uint8_t ep_type;
 
 	if (dwc_otg_host_channel_alloc(td))
@@ -800,24 +801,25 @@ dwc_otg_host_data_rx(struct dwc_otg_td *
 	    temp, DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel)),
 	    DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel)));
 
-	if (temp & HCINT_NAK)
+	if (temp & HCINT_NAK) {
 		td->did_nak = 1;
 
+		/* disable channel - will generate a halted event */
+		DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel),
+		    HCCHAR_CHENA | HCCHAR_CHDIS);
+	}
+
 	if (temp & HCINT_STALL) {
 		td->error_stall = 1;
 		td->error_any = 1;
 		return (0);		/* complete */
 	}
 
-	if (temp & (HCINT_BBLERR |
-	    HCINT_AHBERR | HCINT_CHHLTD | HCINT_XACTERR)) {
+	if (temp & (HCINT_BBLERR | HCINT_AHBERR | HCINT_XACTERR)) {
 		td->error_any = 1;
 		return (0);		/* complete */
 	}
 
-	if (temp & HCINT_XFERCOMPL)
-		td->did_complete = 1;
-
 	/* check endpoint status */
 	if (sc->sc_last_rx_status == 0)
 		goto not_complete;
@@ -826,14 +828,22 @@ dwc_otg_host_data_rx(struct dwc_otg_td *
 		goto not_complete;
 
 	switch (sc->sc_last_rx_status & GRXSTSRD_PKTSTS_MASK) {
+	case GRXSTSRH_HALTED:
+		DPRINTF("HALTED\n");
+		td->did_complete = 1;
+		break;
+	case GRXSTSRH_IN_COMPLETE:
+		DPRINTF("COMPLETE\n");
+		/* disable channel - will generate a halted event */
+		DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel),
+		    HCCHAR_CHENA | HCCHAR_CHDIS);
+		break;
 	case GRXSTSRH_IN_DATA:
 
 		DPRINTF("DATA\n");
 
 		td->toggle ^= 1;
 
-		got_short = 0;
-
 		/* get the packet byte count */
 		count = GRXSTSRD_BCNT_GET(sc->sc_last_rx_status);
 
@@ -842,7 +852,7 @@ dwc_otg_host_data_rx(struct dwc_otg_td *
 			if (count < td->max_packet_size) {
 				/* we have a short packet */
 				td->short_pkt = 1;
-				got_short = 1;
+				td->got_short = 1;
 			} else {
 				/* invalid USB packet */
 				td->error_any = 1;
@@ -863,35 +873,33 @@ dwc_otg_host_data_rx(struct dwc_otg_td *
 			return (0);		/* we are complete */
 		}
 
-		usbd_copy_in(td->pc, td->offset, sc->sc_rx_bounce_buffer, count);
+		usbd_copy_in(td->pc, td->offset,
+		    sc->sc_rx_bounce_buffer, count);
+
 		td->remainder -= count;
 		td->offset += count;
-
-		/* release FIFO */
-		dwc_otg_common_rx_ack(sc);
-
-		/* check if we are complete */
-		if ((td->remainder == 0) || got_short) {
-			if (td->short_pkt) {
-				/* we are complete */
-				return (0);
-			}
-			/* else need to receive a zero length packet */
-		}
 		break;
 
 	default:
 		DPRINTF("OTHER\n");
-
-		/* release FIFO */
-		dwc_otg_common_rx_ack(sc);
 		break;
 	}
+	/* release FIFO */
+	dwc_otg_common_rx_ack(sc);
 
 not_complete:
-	if (td->did_complete == 0 && td->did_nak == 0)
+	if (td->did_complete == 0)
 		return (1);	/* busy */
 
+	/* check if we are complete */
+	if ((td->remainder == 0) || (td->got_short != 0)) {
+		if (td->short_pkt) {
+			/* we are complete */
+			return (0);
+		}
+		/* else need to receive a zero length packet */
+	}
+
 	temp = sc->sc_hcchar[td->channel];
 
 	ep_type = ((temp & HCCHAR_EPTYPE_MASK) >>
@@ -1077,8 +1085,10 @@ dwc_otg_host_data_tx(struct dwc_otg_td *
 	    temp, DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel)),
 	    DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel)));
 
-	if (temp & HCINT_NAK)
+	if (temp & HCINT_NAK) {
 		td->did_nak = 1;
+		td->did_complete = 1;
+	}
 
 	if (temp & HCINT_STALL) {
 		td->error_stall = 1;
@@ -1086,8 +1096,7 @@ dwc_otg_host_data_tx(struct dwc_otg_td *
 		return (0);		/* complete */
 	}
 
-	if (temp & (HCINT_BBLERR |
-	    HCINT_AHBERR | HCINT_CHHLTD | HCINT_XACTERR)) {
+	if (temp & (HCINT_BBLERR | HCINT_AHBERR | HCINT_XACTERR)) {
 		td->error_any = 1;
 		return (0);		/* complete */
 	}
@@ -1509,8 +1518,29 @@ repeat:
 
 			uint8_t ep_no;
 
-			temp = GRXSTSRD_BCNT_GET(
-			    sc->sc_last_rx_status);
+			temp = sc->sc_last_rx_status &
+			    GRXSTSRD_PKTSTS_MASK;
+
+			/* non-data messages we simply skip */
+			if (temp != GRXSTSRD_STP_DATA &&
+			    temp != GRXSTSRD_OUT_DATA) {
+				if (sc->sc_flags.status_device_mode) {
+					dwc_otg_common_rx_ack(sc);
+					goto repeat;
+				} else if (temp != GRXSTSRD_OUT_COMPLETE &&
+				    temp != GRXSTSRH_HALTED) {
+					dwc_otg_common_rx_ack(sc);
+					goto repeat;
+				}
+			}
+
+			if (temp == GRXSTSRH_HALTED || 
+			    temp == GRXSTSRD_OUT_COMPLETE) {
+				temp = 0;
+			} else {
+				temp = GRXSTSRD_BCNT_GET(
+				    sc->sc_last_rx_status);
+			}
 			ep_no = GRXSTSRD_CHNUM_GET(
 			    sc->sc_last_rx_status);
 
@@ -1522,16 +1552,6 @@ repeat:
 				    sc->sc_rx_bounce_buffer, (temp + 3) / 4);
 			}
 
-			temp = sc->sc_last_rx_status &
-			    GRXSTSRD_PKTSTS_MASK;
-
-			/* non-data messages we simply skip */
-			if (temp != GRXSTSRD_STP_DATA &&
-			    temp != GRXSTSRD_OUT_DATA) {
-				dwc_otg_common_rx_ack(sc);
-				goto repeat;
-			}
-
 			/* check if we should dump the data */
 			if (!(sc->sc_active_rx_ep & (1U << ep_no))) {
 				dwc_otg_common_rx_ack(sc);
@@ -1575,12 +1595,6 @@ repeat:
 		if (sc->sc_last_rx_status == 0)
 			goto repeat;
 
-		/* if no host listener - dump data */
-		if (sc->sc_flags.status_device_mode == 0) {
-			dwc_otg_common_rx_ack(sc);
-			goto repeat;
-		}
-
 		/* disable RX FIFO level interrupt */
 		sc->sc_irq_mask &= ~GINTSTS_RXFLVL;
 		DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
@@ -1637,6 +1651,8 @@ dwc_otg_interrupt(struct dwc_otg_softc *
 
 		/* clear left-over interrupts */
 		for (x = 0; x != sc->sc_host_ch_max; x++) {
+			if (!(haint & (1 << x)))
+				continue;
 			/* check if channel is disabled */
 			if (sc->sc_hcchar[x] == 0) {
 				uint32_t temp;
@@ -1845,6 +1861,7 @@ dwc_otg_setup_standard_chain_sub(struct 
 	td->short_pkt = temp->short_pkt;
 	td->alt_next = temp->setup_alt_next;
 	td->set_toggle = 0;
+	td->got_short = 0;
 	td->channel = DWC_OTG_MAX_CHANNELS;
 }
 

Modified: head/sys/dev/usb/controller/dwc_otg.h
==============================================================================
--- head/sys/dev/usb/controller/dwc_otg.h	Wed Sep 12 18:18:14 2012	(r240418)
+++ head/sys/dev/usb/controller/dwc_otg.h	Wed Sep 12 19:15:29 2012	(r240419)
@@ -70,6 +70,7 @@ struct dwc_otg_td {
 	uint8_t set_toggle:1;
 	uint8_t did_nak:1;
 	uint8_t did_complete:1;
+	uint8_t got_short:1;
 };
 
 struct dwc_otg_std_temp {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201209121915.q8CJFTwk031651>