Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 May 2014 14:15:03 +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: r266467 - head/sys/dev/usb/controller
Message-ID:  <201405201415.s4KEF3wx070529@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Tue May 20 14:15:03 2014
New Revision: 266467
URL: http://svnweb.freebsd.org/changeset/base/266467

Log:
  Correct some programming details. The layout of the PDTs were
  different from what was initially thought. Fix re-programming of
  hardware mode register after reset.
  
  Sponsored by:	DARPA, AFRL

Modified:
  head/sys/dev/usb/controller/saf1761_otg.c
  head/sys/dev/usb/controller/saf1761_otg_reg.h

Modified: head/sys/dev/usb/controller/saf1761_otg.c
==============================================================================
--- head/sys/dev/usb/controller/saf1761_otg.c	Tue May 20 12:22:53 2014	(r266466)
+++ head/sys/dev/usb/controller/saf1761_otg.c	Tue May 20 14:15:03 2014	(r266467)
@@ -227,7 +227,7 @@ saf1761_host_channel_alloc(struct saf176
 			if (sc->sc_host_isoc_map & (1 << x))
 				continue;
 			sc->sc_host_isoc_map |= (1 << x);
-			td->channel = 64 + x;
+			td->channel = x;
 			return (0);
 		}
 		break;
@@ -236,7 +236,7 @@ saf1761_host_channel_alloc(struct saf176
 			if (sc->sc_host_async_map & (1 << x))
 				continue;
 			sc->sc_host_async_map |= (1 << x);
-			td->channel = x;
+			td->channel = 64 + x;
 			return (0);
 		}
 		break;
@@ -253,8 +253,8 @@ saf1761_host_channel_free(struct saf1761
 		return;
 
 	/* disable channel */
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 3), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 0), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 3), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 0), 0);
 
 	switch (td->ep_type) {
 	case UE_INTERRUPT:
@@ -263,7 +263,7 @@ saf1761_host_channel_free(struct saf1761
 		td->channel = SOTG_HOST_CHANNEL_MAX;
 		break;
 	case UE_ISOCHRONOUS:
-		x = td->channel - 64;
+		x = td->channel;
 		sc->sc_host_isoc_map &= ~(1 << x);
 		td->channel = SOTG_HOST_CHANNEL_MAX;
 		break;
@@ -276,19 +276,23 @@ saf1761_host_channel_free(struct saf1761
 }
 
 static void
-saf1761_read_host_fifo_1(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td,
-    void *buf, uint32_t len)
+saf1761_read_host_memory_4(struct saf1761_otg_softc *sc, uint32_t offset,
+    void *buf, uint32_t count)
 {
-	bus_space_read_region_1((sc)->sc_io_tag, (sc)->sc_io_hdl,
-	    SOTG_DATA_ADDR(td->channel), buf, len);
+	if (count == 0)
+		return;
+	SAF1761_WRITE_4(sc, SOTG_MEMORY_REG, SOTG_HC_MEMORY_ADDR(offset));
+	DELAY(1);	/* read prefetch time is 90ns */
+	bus_space_read_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl, offset, buf, count);
 }
 
 static void
-saf1761_write_host_fifo_1(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td,
-    void *buf, uint32_t len)
+saf1761_write_host_memory_4(struct saf1761_otg_softc *sc, uint32_t offset,
+    void *buf, uint32_t count)
 {
-	bus_space_write_region_1((sc)->sc_io_tag, (sc)->sc_io_hdl,
-	    SOTG_DATA_ADDR(td->channel), buf, len);
+	if (count == 0)
+		return;
+	bus_space_write_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl, offset, buf, count);
 }
 
 static uint8_t
@@ -299,7 +303,7 @@ saf1761_host_setup_tx(struct saf1761_otg
 	uint32_t count;
 
 	if (td->channel < SOTG_HOST_CHANNEL_MAX) {
-		status = SAF1761_READ_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 3));
+		status = SAF1761_READ_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 3));
 		if (status & (1 << 31)) {
 			goto busy;
 		} else if (status & (1 << 30)) {
@@ -325,23 +329,24 @@ saf1761_host_setup_tx(struct saf1761_otg
 
 	usbd_copy_out(td->pc, 0, &req, count);
 
-	saf1761_write_host_fifo_1(sc, td, &req, count);
+	saf1761_write_host_memory_4(sc, SOTG_DATA_ADDR(td->channel),
+	    &req, (count + 3) / 4);
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 7), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 6), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 5), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 4), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 3),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 7), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 6), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 5), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 4), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 3),
 	    (1 << 31) | (td->toggle << 25) | (3 << 23));
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 2),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 2),
 	    SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8);
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 1),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 1),
 	    td->dw1_value |
 	    (2 << 10) /* SETUP PID */ |
 	    (td->ep_index >> 1));
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 0),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 0),
 	    (td->ep_index << 31) |
 	    (1 << 29) /* pkt-multiplier */ |
 	    (td->max_packet_size << 18) /* wMaxPacketSize */ |
@@ -365,7 +370,7 @@ saf1761_host_bulk_data_rx(struct saf1761
 		uint32_t count;
 		uint8_t got_short;
 
-		status = SAF1761_READ_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 3));
+		status = SAF1761_READ_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 3));
 
 		if (status & (1 << 31)) {
 			goto busy;
@@ -401,8 +406,9 @@ saf1761_host_bulk_data_rx(struct saf1761
 			goto complete;
 		}
 
-		saf1761_read_host_fifo_1(sc, td,
-		    sc->sc_bounce_buffer, count);
+		saf1761_read_host_memory_4(sc, SOTG_DATA_ADDR(td->channel),
+		    sc->sc_bounce_buffer, (count + 3) / 4);
+
 		usbd_copy_in(td->pc, td->offset,
 		    sc->sc_bounce_buffer, count);
 
@@ -429,21 +435,21 @@ saf1761_host_bulk_data_rx(struct saf1761
 
 	/* receive one more packet */
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 7), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 6), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 5), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 4), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 3),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 7), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 6), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 5), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 4), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 3),
 	    (1 << 31) | (td->toggle << 25) | (3 << 23));
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 2),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 2),
 	    SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8);
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 1),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 1),
 	    td->dw1_value |
 	    (1 << 10) /* IN-PID */ |
 	    (td->ep_index >> 1));
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 0),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 0),
 	    (td->ep_index << 31) |
 	    (1 << 29) /* pkt-multiplier */ |
 	    (td->max_packet_size << 18) /* wMaxPacketSize */ |
@@ -463,7 +469,7 @@ saf1761_host_bulk_data_tx(struct saf1761
 	if (td->channel < SOTG_HOST_CHANNEL_MAX) {
 		uint32_t status;
 
-		status = SAF1761_READ_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 3));
+		status = SAF1761_READ_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 3));
 		if (status & (1 << 31)) {
 			goto busy;
 		} else if (status & (1 << 30)) {
@@ -493,7 +499,8 @@ saf1761_host_bulk_data_tx(struct saf1761
 	}
 
 	usbd_copy_out(td->pc, td->offset, sc->sc_bounce_buffer, count);
-	saf1761_write_host_fifo_1(sc, td, sc->sc_bounce_buffer, count);
+	saf1761_write_host_memory_4(sc, SOTG_DATA_ADDR(td->channel),
+	    sc->sc_bounce_buffer, (count + 3) / 4);
 
 	/* set toggle, if any */
 	if (td->set_toggle) {
@@ -501,21 +508,21 @@ saf1761_host_bulk_data_tx(struct saf1761
 		td->toggle = 1;
 	}
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 7), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 6), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 5), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 4), 0);
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 3),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 7), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 6), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 5), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 4), 0);
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 3),
 	    (1 << 31) | (td->toggle << 25) | (3 << 23));
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 2),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 2),
 	    SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8);
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 1),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 1),
 	    td->dw1_value |
 	    (0 << 10) /* OUT-PID */ |
 	    (td->ep_index >> 1));
 
-	SAF1761_WRITE_4(sc, SOTG_ASYNC_PDT(td->channel) + (4 * 0),
+	SAF1761_WRITE_4(sc, SOTG_ISOC_PDT(td->channel) + (4 * 0),
 	    (td->ep_index << 31) |
 	    (1 << 29) /* pkt-multiplier */ |
 	    (td->max_packet_size << 18) /* wMaxPacketSize */ |
@@ -566,6 +573,8 @@ saf1761_otg_set_address(struct saf1761_o
 static void
 saf1761_read_device_fifo_1(struct saf1761_otg_softc *sc, void *buf, uint32_t len)
 {
+	if (len == 0)
+		return;
 	bus_space_read_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl,
 	    SOTG_DATA_PORT, buf, len);
 }
@@ -573,6 +582,8 @@ saf1761_read_device_fifo_1(struct saf176
 static void
 saf1761_write_device_fifo_1(struct saf1761_otg_softc *sc, void *buf, uint32_t len)
 {
+	if (len == 0)
+		return;
 	bus_space_write_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl,
 	    SOTG_DATA_PORT, buf, len);
 }
@@ -1614,10 +1625,29 @@ saf1761_otg_init(struct saf1761_otg_soft
 
 	USB_BUS_LOCK(&sc->sc_bus);
 
+	/* Reset Host controller, including HW mode */
+	SAF1761_WRITE_2(sc, SOTG_SW_RESET, SOTG_SW_RESET_ALL);
+
+	DELAY(1000);
+
+	/* Reset Host controller, including HW mode */
+	SAF1761_WRITE_2(sc, SOTG_SW_RESET, SOTG_SW_RESET_HC);
+
+	/* wait a bit */
+	DELAY(1000);
+
+	SAF1761_WRITE_2(sc, SOTG_SW_RESET, 0);
+
+	/* wait a bit */
+	DELAY(1000);
+
 	/* Enable interrupts */
 	sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_GLOBAL_INTR_EN |
 	    SOTG_HW_MODE_CTRL_COMN_INT;
 
+	/* unlock device */
+	SAF1761_WRITE_2(sc, SOTG_UNLOCK_DEVICE, SOTG_UNLOCK_DEVICE_CODE);
+
 	/*
 	 * Set correct hardware mode, must be written twice if bus
 	 * width is changed:
@@ -1625,7 +1655,14 @@ saf1761_otg_init(struct saf1761_otg_soft
 	SAF1761_WRITE_2(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
 	SAF1761_WRITE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
 
-	DPRINTF("DCID=0x%08x\n", SAF1761_READ_4(sc, SOTG_DCCHIP_ID));
+	SAF1761_WRITE_4(sc, SOTG_DCSCRATCH, 0xdeadbeef);
+
+	DPRINTF("DCID=0x%08x VEND=0x%04x PROD=0x%04x HWMODE=0x%08x SCRATCH=0x%08x\n",
+	    SAF1761_READ_4(sc, SOTG_DCCHIP_ID),
+	    SAF1761_READ_2(sc, SOTG_VEND_ID),
+	    SAF1761_READ_2(sc, SOTG_PROD_ID),
+	    SAF1761_READ_4(sc, SOTG_HW_MODE_CTRL),
+	    SAF1761_READ_4(sc, SOTG_DCSCRATCH));
 
 	/* reset device controller */
 	SAF1761_WRITE_2(sc, SOTG_MODE, SOTG_MODE_SFRESET);
@@ -1635,14 +1672,22 @@ saf1761_otg_init(struct saf1761_otg_soft
 	DELAY(1000);
 
 	/* reset host controller */
-	SAF1761_WRITE_4(sc, SOTG_SW_RESET, SOTG_SW_RESET_HC);
 	SAF1761_WRITE_4(sc, SOTG_USBCMD, SOTG_USBCMD_HCRESET);
 
+	/* wait for reset to clear */
+	for (x = 0; x != 10; x++) {
+		if ((SAF1761_READ_4(sc, SOTG_USBCMD) & SOTG_USBCMD_HCRESET) == 0)
+			break;
+		usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 10);
+	}
+
+	SAF1761_WRITE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode |
+	    SOTG_HW_MODE_CTRL_ALL_ATX_RESET);
+
 	/* wait a bit */
 	DELAY(1000);
 
-	SAF1761_WRITE_4(sc, SOTG_SW_RESET, 0);
-	SAF1761_WRITE_4(sc, SOTG_USBCMD, 0);
+	SAF1761_WRITE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
 
 	/* wait a bit */
 	DELAY(1000);
@@ -1696,10 +1741,14 @@ saf1761_otg_init(struct saf1761_otg_soft
 	    SOTG_DCINTERRUPT_IEBRST | SOTG_DCINTERRUPT_IESUSP;
 	SAF1761_WRITE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable);
 
-	/* connect ATX port 1 to device controller */
+	/*
+	 * Connect ATX port 1 to device controller, select external
+	 * charge pump and driver VBUS to +5V:
+	 */
 	SAF1761_WRITE_2(sc, SOTG_CTRL_CLR, 0xFFFF);
 	SAF1761_WRITE_2(sc, SOTG_CTRL_SET, SOTG_CTRL_SW_SEL_HC_DC |
-	    SOTG_CTRL_BDIS_ACON_EN);
+	    SOTG_CTRL_BDIS_ACON_EN | SOTG_CTRL_SEL_CP_EXT |
+	    SOTG_CTRL_VBUS_DRV);
 
 	/* disable device address */
 	SAF1761_WRITE_1(sc, SOTG_ADDRESS, 0);
@@ -1720,6 +1769,8 @@ saf1761_otg_init(struct saf1761_otg_soft
 	/* start the HC */
 	SAF1761_WRITE_4(sc, SOTG_USBCMD, SOTG_USBCMD_RS);
 
+	DPRINTF("USBCMD=0x%08x\n", SAF1761_READ_4(sc, SOTG_USBCMD));
+
 	/* enable HC interrupts */
 	SAF1761_WRITE_4(sc, SOTG_HCINTERRUPT_ENABLE,
 	    SOTG_HCINTERRUPT_OTG_IRQ |
@@ -2477,7 +2528,8 @@ tr_handle_get_port_status_host:
 
 	temp = SAF1761_READ_4(sc, SOTG_PORTSC1);
 
-	DPRINTFN(9, "port status=0x%04x\n", temp);
+	DPRINTFN(9, "UR_GET_PORT_STATUS on port %d = 0x%08x\n", index, temp);
+
 	i = UPS_HIGH_SPEED;
 
 	if (temp & SOTG_PORTSC1_ECCS)

Modified: head/sys/dev/usb/controller/saf1761_otg_reg.h
==============================================================================
--- head/sys/dev/usb/controller/saf1761_otg_reg.h	Tue May 20 12:22:53 2014	(r266466)
+++ head/sys/dev/usb/controller/saf1761_otg_reg.h	Tue May 20 14:15:03 2014	(r266467)
@@ -78,6 +78,7 @@
 #define	SOTG_TIMER_HIGH_SET 0x38C
 #define	SOTG_TIMER_HIGH_CLR 0x38E
 #define	SOTG_TIMER_START_TMR (1U << 15)
+#define	SOTG_MEMORY_REG 0x33c
 
 /* Peripheral controller specific registers */
 
@@ -188,10 +189,10 @@
 #define	SOTG_PORTSC1_PED (1 << 2)
 #define	SOTG_PORTSC1_ECSC (1 << 1)
 #define	SOTG_PORTSC1_ECCS (1 << 0)
-#define	SOTG_DATA_ADDR(x) (0x400 + (512 * (x)))
-#define	SOTG_ASYNC_PDT(x) (0x400 + (60 * 1024) + ((x) * 32))
-#define	SOTG_INTR_PDT(x) (0x400 + (61 * 1024) + ((x) * 32))
-#define	SOTG_ISOC_PDT(x) (0x400 + (62 * 1024) + ((x) * 32))
+#define	SOTG_DATA_ADDR(x) (0x1000 + (512 * (x)))
+#define	SOTG_ASYNC_PDT(x) (0xC00 + ((x) * 32))
+#define	SOTG_INTR_PDT(x) (0x800 + ((x) * 32))
+#define	SOTG_ISOC_PDT(x) (0x400 + ((x) * 32))
 #define	SOTG_HC_MEMORY_ADDR(x) (((x) - 0x400) >> 3)
 #define	SOTG_SW_RESET 0x30C
 #define	SOTG_SW_RESET_HC (1 << 1)
@@ -210,6 +211,7 @@
 #define	SOTG_USBCMD_LHCR (1 << 7)
 #define	SOTG_USBCMD_HCRESET (1 << 1)
 #define	SOTG_USBCMD_RS (1 << 0)
+#define	SOTG_HCSCRATCH 0x308
 #define	SOTG_HCINTERRUPT 0x310
 #define	SOTG_HCINTERRUPT_OTG_IRQ (1 << 10)
 #define	SOTG_HCINTERRUPT_ISO_IRQ (1 << 9)



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