svn commit: r266467 - head/sys/dev/usb/controller
Hans Petter Selasky
hselasky at FreeBSD.org
Tue May 20 14:15:04 UTC 2014
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)
More information about the svn-src-head
mailing list