aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2014-05-27 10:01:19 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2014-05-27 10:01:19 +0000
commit21c85d9d3b050ad5ab343d0c2e4dcec9fa3579ff (patch)
tree92aaaa8bafcbf568ff76d71add6d3457e5c2e875 /sys/dev
parentd32048bb6d0aea01586e0f522ad33f2e7f492728 (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/controller/saf1761_otg.c759
-rw-r--r--sys/dev/usb/controller/saf1761_otg.h31
-rw-r--r--sys/dev/usb/controller/saf1761_otg_reg.h90
3 files changed, 520 insertions, 360 deletions
diff --git a/sys/dev/usb/controller/saf1761_otg.c b/sys/dev/usb/controller/saf1761_otg.c
index 083fb09dda7a..888face0f3a1 100644
--- a/sys/dev/usb/controller/saf1761_otg.c
+++ b/sys/dev/usb/controller/saf1761_otg.c
@@ -195,9 +195,9 @@ saf1761_otg_wakeup_peer(struct saf1761_otg_softc *sc)
DPRINTFN(5, "\n");
- temp = SAF1761_READ_2(sc, SOTG_MODE);
- SAF1761_WRITE_2(sc, SOTG_MODE, temp | SOTG_MODE_SNDRSU);
- SAF1761_WRITE_2(sc, SOTG_MODE, temp & ~SOTG_MODE_SNDRSU);
+ temp = SAF1761_READ_LE_4(sc, SOTG_MODE);
+ SAF1761_WRITE_LE_4(sc, SOTG_MODE, temp | SOTG_MODE_SNDRSU);
+ SAF1761_WRITE_LE_4(sc, SOTG_MODE, temp & ~SOTG_MODE_SNDRSU);
/* Wait 8ms for remote wakeup to complete. */
usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 125);
@@ -253,8 +253,8 @@ saf1761_host_channel_free(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
return;
/* disable channel */
- SAF1761_WRITE_4(sc, SOTG_PDT(td->channel) + SOTG_PDT_DW3, 0);
- SAF1761_WRITE_4(sc, SOTG_PDT(td->channel) + SOTG_PDT_DW0, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_PTD(td->channel) + SOTG_PTD_DW3, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_PTD(td->channel) + SOTG_PTD_DW0, 0);
switch (td->ep_type) {
case UE_INTERRUPT:
@@ -275,49 +275,143 @@ saf1761_host_channel_free(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
}
}
+static uint32_t
+saf1761_peek_host_memory_le_4(struct saf1761_otg_softc *sc, uint32_t offset)
+{
+ SAF1761_WRITE_LE_4(sc, SOTG_MEMORY_REG, offset);
+ SAF1761_90NS_DELAY(sc); /* read prefetch time is 90ns */
+ return (SAF1761_READ_LE_4(sc, offset));
+}
+
static void
-saf1761_read_host_memory_4(struct saf1761_otg_softc *sc, uint32_t offset,
- void *buf, uint32_t count)
+saf1761_read_host_memory(struct saf1761_otg_softc *sc,
+ struct saf1761_otg_td *td, uint32_t len)
{
- if (count == 0)
+ struct usb_page_search buf_res;
+ uint32_t offset;
+ uint32_t count;
+
+ if (len == 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);
+
+ offset = SOTG_DATA_ADDR(td->channel);
+ SAF1761_WRITE_LE_4(sc, SOTG_MEMORY_REG, offset);
+ SAF1761_90NS_DELAY(sc); /* read prefetch time is 90ns */
+
+ /* optimised read first */
+ while (len > 0) {
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > len)
+ buf_res.length = len;
+
+ /* check buffer alignment */
+ if (((uintptr_t)buf_res.buffer) & 3)
+ break;
+
+ count = buf_res.length & ~3;
+ if (count == 0)
+ break;
+
+ bus_space_read_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ offset, buf_res.buffer, count / 4);
+
+ len -= count;
+ offset += count;
+
+ /* update remainder and offset */
+ td->remainder -= count;
+ td->offset += count;
+ }
+
+ if (len > 0) {
+ /* use bounce buffer */
+ bus_space_read_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ offset, sc->sc_bounce_buffer, (len + 3) / 4);
+ usbd_copy_in(td->pc, td->offset,
+ sc->sc_bounce_buffer, len);
+
+ /* update remainder and offset */
+ td->remainder -= len;
+ td->offset += len;
+ }
}
static void
-saf1761_write_host_memory_4(struct saf1761_otg_softc *sc, uint32_t offset,
- void *buf, uint32_t count)
+saf1761_write_host_memory(struct saf1761_otg_softc *sc,
+ struct saf1761_otg_td *td, uint32_t len)
{
- if (count == 0)
+ struct usb_page_search buf_res;
+ uint32_t offset;
+ uint32_t count;
+
+ if (len == 0)
return;
- bus_space_write_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl, offset, buf, count);
+
+ offset = SOTG_DATA_ADDR(td->channel);
+
+ /* optimised write first */
+ while (len > 0) {
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > len)
+ buf_res.length = len;
+
+ /* check buffer alignment */
+ if (((uintptr_t)buf_res.buffer) & 3)
+ break;
+
+ count = buf_res.length & ~3;
+ if (count == 0)
+ break;
+
+ bus_space_write_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ offset, buf_res.buffer, count / 4);
+
+ len -= count;
+ offset += count;
+
+ /* update remainder and offset */
+ td->remainder -= count;
+ td->offset += count;
+ }
+ if (len > 0) {
+ /* use bounce buffer */
+ usbd_copy_out(td->pc, td->offset, sc->sc_bounce_buffer, len);
+ bus_space_write_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ offset, sc->sc_bounce_buffer, (len + 3) / 4);
+
+ /* update remainder and offset */
+ td->remainder -= len;
+ td->offset += len;
+ }
}
static uint8_t
saf1761_host_setup_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
{
- struct usb_device_request req __aligned(4);
uint32_t pdt_addr;
uint32_t status;
uint32_t count;
uint32_t temp;
if (td->channel < SOTG_HOST_CHANNEL_MAX) {
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- saf1761_read_host_memory_4(sc, pdt_addr + SOTG_PDT_DW3, &status, 1);
+ status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
+ DPRINTFN(5, "STATUS=0x%08x\n", status);
- if (status & SOTG_PDT_DW3_ACTIVE) {
+ if (status & SOTG_PTD_DW3_ACTIVE) {
goto busy;
- } else if (status & SOTG_PDT_DW3_HALTED) {
+ } else if (status & SOTG_PTD_DW3_HALTED) {
td->error_stall = 1;
td->error_any = 1;
- } else if (status & SOTG_PDT_DW3_ERRORS) {
+ } else if (status & SOTG_PTD_DW3_ERRORS) {
td->error_any = 1;
}
- count = (status & SOTG_PDT_DW3_XFER_COUNT);
+ count = (status & SOTG_PTD_DW3_XFER_COUNT);
saf1761_host_channel_free(sc, td);
goto complete;
@@ -325,42 +419,37 @@ saf1761_host_setup_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
if (saf1761_host_channel_alloc(sc, td))
goto busy;
- if (sizeof(req) != td->remainder) {
+ count = 8;
+
+ if (count != td->remainder) {
td->error_any = 1;
goto complete;
}
- count = sizeof(req);
-
- usbd_copy_out(td->pc, 0, &req, count);
+ saf1761_write_host_memory(sc, td, count);
- saf1761_write_host_memory_4(sc, SOTG_DATA_ADDR(td->channel),
- &req, (count + 3) / 4);
+ pdt_addr = SOTG_PTD(td->channel);
- pdt_addr = SOTG_PDT(td->channel);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW7, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW6, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW5, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW4, 0);
-
- temp = SOTG_PDT_DW3_ACTIVE | (td->toggle << 25) | SOTG_PDT_DW3_CERR;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW3, temp);
+ temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
temp = SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW2, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp);
temp = td->dw1_value | (2 << 10) /* SETUP PID */ | (td->ep_index >> 1);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW1, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp);
temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ |
(td->max_packet_size << 18) /* wMaxPacketSize */ |
(count << 3) /* transfer count */ |
- SOTG_PDT_DW0_VALID;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW0, temp);
+ SOTG_PTD_DW0_VALID;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
- td->offset += count;
- td->remainder -= count;
td->toggle = 1;
busy:
return (1); /* busy */
@@ -379,21 +468,22 @@ saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
uint32_t count;
uint8_t got_short;
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- saf1761_read_host_memory_4(sc, pdt_addr + SOTG_PDT_DW3, &status, 1);
+ status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
+ DPRINTFN(5, "STATUS=0x%08x\n", status);
- if (status & SOTG_PDT_DW3_ACTIVE) {
+ if (status & SOTG_PTD_DW3_ACTIVE) {
goto busy;
- } else if (status & SOTG_PDT_DW3_HALTED) {
+ } else if (status & SOTG_PTD_DW3_HALTED) {
td->error_stall = 1;
td->error_any = 1;
goto complete;
- } else if (status & SOTG_PDT_DW3_ERRORS) {
+ } else if (status & SOTG_PTD_DW3_ERRORS) {
td->error_any = 1;
goto complete;
}
- count = (status & SOTG_PDT_DW3_XFER_COUNT);
+ count = (status & SOTG_PTD_DW3_XFER_COUNT);
got_short = 0;
/* verify the packet byte count */
@@ -417,14 +507,7 @@ saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
goto complete;
}
- 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);
-
- td->remainder -= count;
- td->offset += count;
+ saf1761_read_host_memory(sc, td, count);
saf1761_host_channel_free(sc, td);
@@ -446,27 +529,27 @@ saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
/* receive one more packet */
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW7, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW6, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW5, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW4, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0);
- temp = SOTG_PDT_DW3_ACTIVE | (td->toggle << 25) | SOTG_PDT_DW3_CERR;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW3, temp);
+ temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
temp = SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW2, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp);
temp = td->dw1_value | (1 << 10) /* IN-PID */ | (td->ep_index >> 1);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW1, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp);
temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ |
(td->max_packet_size << 18) /* wMaxPacketSize */ |
(td->max_packet_size << 3) /* transfer count */ |
- SOTG_PDT_DW0_VALID;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW0, temp);
+ SOTG_PTD_DW0_VALID;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
busy:
return (1); /* busy */
complete:
@@ -483,16 +566,17 @@ saf1761_host_bulk_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
if (td->channel < SOTG_HOST_CHANNEL_MAX) {
uint32_t status;
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- saf1761_read_host_memory_4(sc, pdt_addr + SOTG_PDT_DW3, &status, 1);
+ status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
+ DPRINTFN(5, "STATUS=0x%08x\n", status);
- if (status & SOTG_PDT_DW3_ACTIVE) {
+ if (status & SOTG_PTD_DW3_ACTIVE) {
goto busy;
- } else if (status & SOTG_PDT_DW3_HALTED) {
+ } else if (status & SOTG_PTD_DW3_HALTED) {
td->error_stall = 1;
td->error_any = 1;
- } else if (status & SOTG_PDT_DW3_ERRORS) {
+ } else if (status & SOTG_PTD_DW3_ERRORS) {
td->error_any = 1;
}
@@ -515,9 +599,7 @@ saf1761_host_bulk_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
count = td->remainder;
}
- usbd_copy_out(td->pc, td->offset, sc->sc_bounce_buffer, count);
- saf1761_write_host_memory_4(sc, SOTG_DATA_ADDR(td->channel),
- sc->sc_bounce_buffer, (count + 3) / 4);
+ saf1761_write_host_memory(sc, td, count);
/* set toggle, if any */
if (td->set_toggle) {
@@ -527,30 +609,28 @@ saf1761_host_bulk_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
/* send one more packet */
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW7, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW6, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW5, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW4, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0);
- temp = SOTG_PDT_DW3_ACTIVE | (td->toggle << 25) | SOTG_PDT_DW3_CERR;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW3, temp);
+ temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
temp = SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW2, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp);
temp = td->dw1_value | (0 << 10) /* OUT-PID */ | (td->ep_index >> 1);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW1, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp);
temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ |
(td->max_packet_size << 18) /* wMaxPacketSize */ |
(count << 3) /* transfer count */ |
- SOTG_PDT_DW0_VALID;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW0, temp);
+ SOTG_PTD_DW0_VALID;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
- td->offset += count;
- td->remainder -= count;
td->toggle ^= 1;
busy:
return (1); /* busy */
@@ -569,19 +649,20 @@ saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
uint32_t count;
uint8_t got_short;
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- saf1761_read_host_memory_4(sc, pdt_addr + SOTG_PDT_DW3, &status, 1);
+ status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
+ DPRINTFN(5, "STATUS=0x%08x\n", status);
- if (status & SOTG_PDT_DW3_ACTIVE) {
+ if (status & SOTG_PTD_DW3_ACTIVE) {
goto busy;
- } else if (status & SOTG_PDT_DW3_HALTED) {
+ } else if (status & SOTG_PTD_DW3_HALTED) {
td->error_stall = 1;
td->error_any = 1;
goto complete;
}
- count = (status & SOTG_PDT_DW3_XFER_COUNT);
+ count = (status & SOTG_PTD_DW3_XFER_COUNT);
got_short = 0;
/* verify the packet byte count */
@@ -605,14 +686,7 @@ saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
goto complete;
}
- 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);
-
- td->remainder -= count;
- td->offset += count;
+ saf1761_read_host_memory(sc, td, count);
saf1761_host_channel_free(sc, td);
@@ -634,31 +708,31 @@ saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
/* receive one more packet */
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW7, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW6, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0);
temp = (0xFC << td->uframe) & 0xFF; /* complete split */
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW5, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, temp);
temp = (1U << td->uframe); /* start split */
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW4, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp);
- temp = SOTG_PDT_DW3_ACTIVE | (td->toggle << 25) | SOTG_PDT_DW3_CERR;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW3, temp);
+ temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
- temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | td->interval;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW2, temp);
+ temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | (td->interval & 0xF8);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp);
temp = td->dw1_value | (1 << 10) /* IN-PID */ | (td->ep_index >> 1);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW1, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp);
temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ |
(td->max_packet_size << 18) /* wMaxPacketSize */ |
(td->max_packet_size << 3) /* transfer count */ |
- SOTG_PDT_DW0_VALID;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW0, temp);
+ SOTG_PTD_DW0_VALID;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
busy:
return (1); /* busy */
complete:
@@ -675,13 +749,14 @@ saf1761_host_intr_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
if (td->channel < SOTG_HOST_CHANNEL_MAX) {
uint32_t status;
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- saf1761_read_host_memory_4(sc, pdt_addr + SOTG_PDT_DW3, &status, 1);
+ status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
+ DPRINTFN(5, "STATUS=0x%08x\n", status);
- if (status & SOTG_PDT_DW3_ACTIVE) {
+ if (status & SOTG_PTD_DW3_ACTIVE) {
goto busy;
- } else if (status & SOTG_PDT_DW3_HALTED) {
+ } else if (status & SOTG_PTD_DW3_HALTED) {
td->error_stall = 1;
td->error_any = 1;
}
@@ -705,9 +780,7 @@ saf1761_host_intr_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
count = td->remainder;
}
- usbd_copy_out(td->pc, td->offset, sc->sc_bounce_buffer, count);
- saf1761_write_host_memory_4(sc, SOTG_DATA_ADDR(td->channel),
- sc->sc_bounce_buffer, (count + 3) / 4);
+ saf1761_write_host_memory(sc, td, count);
/* set toggle, if any */
if (td->set_toggle) {
@@ -717,34 +790,32 @@ saf1761_host_intr_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
/* send one more packet */
- pdt_addr = SOTG_PDT(td->channel);
+ pdt_addr = SOTG_PTD(td->channel);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW7, 0);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW6, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0);
temp = (0xFC << td->uframe) & 0xFF; /* complete split */
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW5, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, temp);
temp = (1U << td->uframe); /* start split */
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW4, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp);
- temp = SOTG_PDT_DW3_ACTIVE | (td->toggle << 25) | SOTG_PDT_DW3_CERR;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW3, temp);
+ temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
- temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | td->interval;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW2, temp);
+ temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | (td->interval & 0xF8);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp);
temp = td->dw1_value | (0 << 10) /* OUT-PID */ | (td->ep_index >> 1);
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW1, temp);
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp);
temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ |
(td->max_packet_size << 18) /* wMaxPacketSize */ |
(count << 3) /* transfer count */ |
- SOTG_PDT_DW0_VALID;
- SAF1761_WRITE_4(sc, pdt_addr + SOTG_PDT_DW0, temp);
+ SOTG_PTD_DW0_VALID;
+ SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
- td->offset += count;
- td->remainder -= count;
td->toggle ^= 1;
busy:
return (1); /* busy */
@@ -769,43 +840,117 @@ saf1761_otg_set_address(struct saf1761_otg_softc *sc, uint8_t addr)
{
DPRINTFN(5, "addr=%d\n", addr);
- SAF1761_WRITE_1(sc, SOTG_ADDRESS, addr | SOTG_ADDRESS_ENABLE);
+ SAF1761_WRITE_LE_4(sc, SOTG_ADDRESS, addr | SOTG_ADDRESS_ENABLE);
}
+
static void
-saf1761_read_device_fifo_1(struct saf1761_otg_softc *sc, void *buf, uint32_t len)
+saf1761_read_device_fifo(struct saf1761_otg_softc *sc,
+ struct saf1761_otg_td *td, 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);
+ struct usb_page_search buf_res;
+ uint32_t count;
+
+ /* optimised read first */
+ while (len > 0) {
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > len)
+ buf_res.length = len;
+
+ /* check buffer alignment */
+ if (((uintptr_t)buf_res.buffer) & 3)
+ break;
+
+ count = buf_res.length & ~3;
+ if (count == 0)
+ break;
+
+ bus_space_read_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ SOTG_DATA_PORT, buf_res.buffer, count / 4);
+
+ len -= count;
+
+ /* update remainder and offset */
+ td->remainder -= count;
+ td->offset += count;
+ }
+
+ if (len > 0) {
+ /* use bounce buffer */
+ bus_space_read_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ SOTG_DATA_PORT, sc->sc_bounce_buffer, (len + 3) / 4);
+ usbd_copy_in(td->pc, td->offset,
+ sc->sc_bounce_buffer, len);
+
+ /* update remainder and offset */
+ td->remainder -= len;
+ td->offset += len;
+ }
}
static void
-saf1761_write_device_fifo_1(struct saf1761_otg_softc *sc, void *buf, uint32_t len)
+saf1761_write_device_fifo(struct saf1761_otg_softc *sc,
+ struct saf1761_otg_td *td, 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);
+ struct usb_page_search buf_res;
+ uint32_t count;
+
+ /* optimised write first */
+ while (len > 0) {
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > len)
+ buf_res.length = len;
+
+ /* check buffer alignment */
+ if (((uintptr_t)buf_res.buffer) & 3)
+ break;
+
+ count = buf_res.length & ~3;
+ if (count == 0)
+ break;
+
+ bus_space_write_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ SOTG_DATA_PORT, buf_res.buffer, count / 4);
+
+ len -= count;
+
+ /* update remainder and offset */
+ td->remainder -= count;
+ td->offset += count;
+ }
+ if (len > 0) {
+ /* use bounce buffer */
+ usbd_copy_out(td->pc, td->offset, sc->sc_bounce_buffer, len);
+ bus_space_write_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl,
+ SOTG_DATA_PORT, sc->sc_bounce_buffer, (len + 3) / 4);
+
+ /* update remainder and offset */
+ td->remainder -= len;
+ td->offset += len;
+ }
}
static uint8_t
saf1761_device_setup_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
{
struct usb_device_request req;
- uint16_t count;
+ uint32_t count;
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+
+ count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH);
/* check buffer status */
- if ((SAF1761_READ_1(sc, SOTG_DCBUFFERSTATUS) &
- SOTG_DCBUFFERSTATUS_FILLED_MASK) == 0)
+ if ((count & SOTG_BUF_LENGTH_FILLED_MASK) == 0)
goto busy;
- /* read buffer length */
- count = SAF1761_READ_2(sc, SOTG_BUF_LENGTH);
+ /* get buffer length */
+ count &= SOTG_BUF_LENGTH_BUFLEN_MASK;
DPRINTFN(5, "count=%u rem=%u\n", count, td->remainder);
@@ -813,7 +958,7 @@ saf1761_device_setup_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
td->did_stall = 0;
/* clear stall */
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, 0);
/* verify data length */
if (count != td->remainder) {
@@ -827,15 +972,12 @@ saf1761_device_setup_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
goto busy;
}
/* receive data */
- saf1761_read_device_fifo_1(sc, &req, sizeof(req));
+ saf1761_read_device_fifo(sc, td, sizeof(req));
- /* copy data into real buffer */
- usbd_copy_in(td->pc, 0, &req, sizeof(req));
+ /* extract SETUP packet again */
+ usbd_copy_out(td->pc, 0, &req, sizeof(req));
- td->offset = sizeof(req);
- td->remainder = 0;
-
- /* sneak peek the set address */
+ /* sneak peek the set address request */
if ((req.bmRequestType == UT_WRITE_DEVICE) &&
(req.bRequest == UR_SET_ADDRESS)) {
sc->sc_dv_addr = req.wValue[0] & 0x7F;
@@ -851,7 +993,7 @@ busy:
DPRINTFN(5, "stalling\n");
/* set stall */
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_STALL);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_STALL);
td->did_stall = 1;
}
@@ -861,17 +1003,17 @@ busy:
static uint8_t
saf1761_device_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
{
- struct usb_page_search buf_res;
- uint16_t count;
+ uint32_t count;
uint8_t got_short = 0;
if (td->ep_index == 0) {
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+
+ count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH);
/* check buffer status */
- if ((SAF1761_READ_1(sc, SOTG_DCBUFFERSTATUS) &
- SOTG_DCBUFFERSTATUS_FILLED_MASK) != 0) {
+ if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) {
if (td->remainder == 0) {
/*
@@ -890,23 +1032,24 @@ saf1761_device_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
}
}
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX,
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX,
(td->ep_index << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) |
SOTG_EP_INDEX_DIR_OUT);
/* enable data stage */
if (td->set_toggle) {
td->set_toggle = 0;
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_DSEN);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_DSEN);
}
+ count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH);
+
/* check buffer status */
- if ((SAF1761_READ_1(sc, SOTG_DCBUFFERSTATUS) &
- SOTG_DCBUFFERSTATUS_FILLED_MASK) == 0) {
+ if ((count & SOTG_BUF_LENGTH_FILLED_MASK) == 0)
return (1); /* not complete */
- }
- /* read buffer length */
- count = SAF1761_READ_2(sc, SOTG_BUF_LENGTH);
+
+ /* get buffer length */
+ count &= SOTG_BUF_LENGTH_BUFLEN_MASK;
DPRINTFN(5, "rem=%u count=0x%04x\n", td->remainder, count);
@@ -928,21 +1071,9 @@ saf1761_device_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
td->error_any = 1;
return (0); /* we are complete */
}
- while (count > 0) {
- usbd_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count)
- buf_res.length = count;
-
- /* receive data */
- saf1761_read_device_fifo_1(sc, buf_res.buffer, buf_res.length);
+ /* receive data */
+ saf1761_read_device_fifo(sc, td, count);
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
/* check if we are complete */
if ((td->remainder == 0) || got_short) {
if (td->short_pkt) {
@@ -957,17 +1088,16 @@ saf1761_device_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
static uint8_t
saf1761_device_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
{
- struct usb_page_search buf_res;
- uint16_t count;
- uint16_t count_old;
+ uint32_t count;
if (td->ep_index == 0) {
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+
+ count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH);
/* check buffer status */
- if ((SAF1761_READ_1(sc, SOTG_DCBUFFERSTATUS) &
- SOTG_DCBUFFERSTATUS_FILLED_MASK) != 0) {
+ if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) {
DPRINTFN(5, "SETUP abort\n");
/*
* USB Host Aborted the transfer.
@@ -977,20 +1107,20 @@ saf1761_device_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
}
}
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX,
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX,
(td->ep_index << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) |
SOTG_EP_INDEX_DIR_IN);
+ count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH);
+
/* check buffer status */
- if ((SAF1761_READ_1(sc, SOTG_DCBUFFERSTATUS) &
- SOTG_DCBUFFERSTATUS_FILLED_MASK) != 0) {
+ if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0)
return (1); /* not complete */
- }
/* enable data stage */
if (td->set_toggle) {
td->set_toggle = 0;
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_DSEN);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_DSEN);
}
DPRINTFN(5, "rem=%u\n", td->remainder);
@@ -1001,34 +1131,18 @@ saf1761_device_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
td->short_pkt = 1;
count = td->remainder;
}
- count_old = count;
-
- while (count > 0) {
-
- usbd_get_page(td->pc, td->offset, &buf_res);
-
- /* get correct length */
- if (buf_res.length > count)
- buf_res.length = count;
-
- /* transmit data */
- saf1761_write_device_fifo_1(sc, buf_res.buffer, buf_res.length);
-
- /* update counters */
- count -= buf_res.length;
- td->offset += buf_res.length;
- td->remainder -= buf_res.length;
- }
+ /* transmit data */
+ saf1761_write_device_fifo(sc, td, count);
if (td->ep_index == 0) {
- if (count_old < SOTG_FS_MAX_PACKET_SIZE) {
+ if (count < SOTG_FS_MAX_PACKET_SIZE) {
/* set end of packet */
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_VENDP);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_VENDP);
}
} else {
- if (count_old < SOTG_HS_MAX_PACKET_SIZE) {
+ if (count < SOTG_HS_MAX_PACKET_SIZE) {
/* set end of packet */
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_VENDP);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_VENDP);
}
}
@@ -1045,25 +1159,29 @@ saf1761_device_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
static uint8_t
saf1761_device_data_tx_sync(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
{
+ uint32_t count;
+
if (td->ep_index == 0) {
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP);
+
+ count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH);
/* check buffer status */
- if ((SAF1761_READ_1(sc, SOTG_DCBUFFERSTATUS) &
- SOTG_DCBUFFERSTATUS_FILLED_MASK) != 0) {
+ if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) {
DPRINTFN(5, "Faking complete\n");
return (0); /* complete */
}
}
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX,
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX,
(td->ep_index << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) |
SOTG_EP_INDEX_DIR_IN);
+ count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH);
+
/* check buffer status */
- if ((SAF1761_READ_1(sc, SOTG_DCBUFFERSTATUS) &
- SOTG_DCBUFFERSTATUS_FILLED_MASK) != 0)
+ if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0)
return (1); /* busy */
if (sc->sc_dv_addr != 0xFF) {
@@ -1143,7 +1261,7 @@ saf1761_otg_wait_suspend(struct saf1761_otg_softc *sc, uint8_t on)
sc->sc_intr_enable &= ~SOTG_DCINTERRUPT_IESUSP;
sc->sc_intr_enable |= SOTG_DCINTERRUPT_IERESM;
}
- SAF1761_WRITE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable);
+ SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable);
}
static void
@@ -1152,7 +1270,7 @@ saf1761_otg_update_vbus(struct saf1761_otg_softc *sc)
uint16_t status;
/* read fresh status */
- status = SAF1761_READ_2(sc, SOTG_STATUS);
+ status = SAF1761_READ_LE_4(sc, SOTG_STATUS);
DPRINTFN(4, "STATUS=0x%04x\n", status);
@@ -1188,16 +1306,18 @@ saf1761_otg_interrupt(struct saf1761_otg_softc *sc)
USB_BUS_LOCK(&sc->sc_bus);
- hcstat = SAF1761_READ_4(sc, SOTG_HCINTERRUPT);
+ hcstat = SAF1761_READ_LE_4(sc, SOTG_HCINTERRUPT);
/* acknowledge all host controller interrupts */
- SAF1761_WRITE_4(sc, SOTG_HCINTERRUPT, hcstat);
+ SAF1761_WRITE_LE_4(sc, SOTG_HCINTERRUPT, hcstat);
- status = SAF1761_READ_4(sc, SOTG_DCINTERRUPT);
+ status = SAF1761_READ_LE_4(sc, SOTG_DCINTERRUPT);
/* acknowledge all device controller interrupts */
- SAF1761_WRITE_4(sc, SOTG_DCINTERRUPT, status);
+ SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT, status);
- DPRINTF("DCINTERRUPT=0x%08x HCINTERRUPT=0x%08x SOF=0x%04x\n",
- status, hcstat, SAF1761_READ_2(sc, SOTG_FRAME_NUM));
+ DPRINTF("DCINTERRUPT=0x%08x HCINTERRUPT=0x%08x SOF=0x%08x "
+ "FRINDEX=0x%08x\n", status, hcstat,
+ SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM),
+ SAF1761_READ_LE_4(sc, SOTG_FRINDEX));
/* update VBUS and ID bits, if any */
if (status & SOTG_DCINTERRUPT_IEVBUS) {
@@ -1206,11 +1326,11 @@ saf1761_otg_interrupt(struct saf1761_otg_softc *sc)
if (status & SOTG_DCINTERRUPT_IEBRST) {
/* unlock device */
- SAF1761_WRITE_2(sc, SOTG_UNLOCK_DEVICE,
+ SAF1761_WRITE_LE_4(sc, SOTG_UNLOCK_DEVICE,
SOTG_UNLOCK_DEVICE_CODE);
/* Enable device address */
- SAF1761_WRITE_1(sc, SOTG_ADDRESS,
+ SAF1761_WRITE_LE_4(sc, SOTG_ADDRESS,
SOTG_ADDRESS_ENABLE);
sc->sc_flags.status_bus_reset = 1;
@@ -1230,7 +1350,7 @@ saf1761_otg_interrupt(struct saf1761_otg_softc *sc)
*/
if (status & SOTG_DCINTERRUPT_IERESM) {
/* unlock device */
- SAF1761_WRITE_2(sc, SOTG_UNLOCK_DEVICE,
+ SAF1761_WRITE_LE_4(sc, SOTG_UNLOCK_DEVICE,
SOTG_UNLOCK_DEVICE_CODE);
if (sc->sc_flags.status_suspend) {
@@ -1529,7 +1649,7 @@ saf1761_otg_intr_set(struct usb_xfer *xfer, uint8_t set)
else
sc->sc_intr_enable &= ~mask;
- SAF1761_WRITE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable);
+ SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable);
}
static void
@@ -1751,13 +1871,13 @@ saf1761_otg_set_stall(struct usb_device *udev,
return;
}
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX,
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX,
(ep_no << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) |
((ep_dir == UE_DIR_IN) ? SOTG_EP_INDEX_DIR_IN :
SOTG_EP_INDEX_DIR_OUT));
/* set stall */
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_STALL);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_STALL);
}
static void
@@ -1769,20 +1889,20 @@ saf1761_otg_clear_stall_sub(struct saf1761_otg_softc *sc,
return;
}
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX,
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX,
(ep_no << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) |
((ep_dir == UE_DIR_IN) ? SOTG_EP_INDEX_DIR_IN :
SOTG_EP_INDEX_DIR_OUT));
/* disable endpoint */
- SAF1761_WRITE_2(sc, SOTG_EP_TYPE, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_TYPE, 0);
/* enable endpoint again - will clear data toggle */
- SAF1761_WRITE_2(sc, SOTG_EP_TYPE, ep_type | SOTG_EP_TYPE_ENABLE);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_TYPE, ep_type | SOTG_EP_TYPE_ENABLE);
/* clear buffer */
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_CLBUF);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_CLBUF);
/* clear stall */
- SAF1761_WRITE_1(sc, SOTG_CTRL_FUNC, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, 0);
}
static void
@@ -1828,17 +1948,17 @@ saf1761_otg_init(struct saf1761_otg_softc *sc)
USB_BUS_LOCK(&sc->sc_bus);
/* Reset Host controller, including HW mode */
- SAF1761_WRITE_2(sc, SOTG_SW_RESET, SOTG_SW_RESET_ALL);
+ SAF1761_WRITE_LE_4(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);
+ SAF1761_WRITE_LE_4(sc, SOTG_SW_RESET, SOTG_SW_RESET_HC);
/* wait a bit */
DELAY(1000);
- SAF1761_WRITE_2(sc, SOTG_SW_RESET, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_SW_RESET, 0);
/* wait a bit */
DELAY(1000);
@@ -1848,48 +1968,49 @@ saf1761_otg_init(struct saf1761_otg_softc *sc)
SOTG_HW_MODE_CTRL_COMN_INT;
/* unlock device */
- SAF1761_WRITE_2(sc, SOTG_UNLOCK_DEVICE, SOTG_UNLOCK_DEVICE_CODE);
+ SAF1761_WRITE_LE_4(sc, SOTG_UNLOCK_DEVICE, SOTG_UNLOCK_DEVICE_CODE);
/*
* Set correct hardware mode, must be written twice if bus
* width is changed:
*/
- SAF1761_WRITE_2(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
- SAF1761_WRITE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
+ SAF1761_WRITE_LE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
+ SAF1761_WRITE_LE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
- SAF1761_WRITE_4(sc, SOTG_DCSCRATCH, 0xdeadbeef);
+ SAF1761_WRITE_LE_4(sc, SOTG_DCSCRATCH, 0xdeadbeef);
+ SAF1761_WRITE_LE_4(sc, SOTG_HCSCRATCH, 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));
+ DPRINTF("DCID=0x%08x VEND_PROD=0x%08x HWMODE=0x%08x SCRATCH=0x%08x,0x%08x\n",
+ SAF1761_READ_LE_4(sc, SOTG_DCCHIP_ID),
+ SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID),
+ SAF1761_READ_LE_4(sc, SOTG_HW_MODE_CTRL),
+ SAF1761_READ_LE_4(sc, SOTG_DCSCRATCH),
+ SAF1761_READ_LE_4(sc, SOTG_HCSCRATCH));
/* reset device controller */
- SAF1761_WRITE_2(sc, SOTG_MODE, SOTG_MODE_SFRESET);
- SAF1761_WRITE_2(sc, SOTG_MODE, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_MODE, SOTG_MODE_SFRESET);
+ SAF1761_WRITE_LE_4(sc, SOTG_MODE, 0);
/* wait a bit */
DELAY(1000);
/* reset host controller */
- SAF1761_WRITE_4(sc, SOTG_USBCMD, SOTG_USBCMD_HCRESET);
+ SAF1761_WRITE_LE_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)
+ if ((SAF1761_READ_LE_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 |
+ SAF1761_WRITE_LE_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_HW_MODE_CTRL, sc->sc_hw_mode);
+ SAF1761_WRITE_LE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode);
/* wait a bit */
DELAY(1000);
@@ -1907,74 +2028,94 @@ saf1761_otg_init(struct saf1761_otg_softc *sc)
break;
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX,
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX,
(x << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) |
SOTG_EP_INDEX_DIR_IN);
/* select the maximum packet size */
- SAF1761_WRITE_2(sc, SOTG_EP_MAXPACKET, pf->max_in_frame_size);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_MAXPACKET, pf->max_in_frame_size);
/* select the correct endpoint */
- SAF1761_WRITE_1(sc, SOTG_EP_INDEX,
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX,
(x << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) |
SOTG_EP_INDEX_DIR_OUT);
/* select the maximum packet size */
- SAF1761_WRITE_2(sc, SOTG_EP_MAXPACKET, pf->max_out_frame_size);
+ SAF1761_WRITE_LE_4(sc, SOTG_EP_MAXPACKET, pf->max_out_frame_size);
}
/* enable interrupts */
- SAF1761_WRITE_2(sc, SOTG_MODE, SOTG_MODE_GLINTENA |
+ SAF1761_WRITE_LE_4(sc, SOTG_MODE, SOTG_MODE_GLINTENA |
SOTG_MODE_CLKAON | SOTG_MODE_WKUPCS);
/* set default values */
- SAF1761_WRITE_1(sc, SOTG_INTERRUPT_CFG,
+ SAF1761_WRITE_LE_4(sc, SOTG_INTERRUPT_CFG,
SOTG_INTERRUPT_CFG_CDBGMOD |
SOTG_INTERRUPT_CFG_DDBGMODIN |
SOTG_INTERRUPT_CFG_DDBGMODOUT);
/* enable VBUS and ID interrupt */
- SAF1761_WRITE_2(sc, SOTG_IRQ_ENABLE_CLR, 0xFFFF);
- SAF1761_WRITE_2(sc, SOTG_IRQ_ENABLE_SET,
- SOTG_IRQ_ID | SOTG_IRQ_VBUS_VLD);
+ SAF1761_WRITE_LE_4(sc, SOTG_IRQ_ENABLE_SET_CLR,
+ SOTG_IRQ_ENABLE_CLR(0xFFFF));
+ SAF1761_WRITE_LE_4(sc, SOTG_IRQ_ENABLE_SET_CLR,
+ SOTG_IRQ_ENABLE_SET(SOTG_IRQ_ID | SOTG_IRQ_VBUS_VLD));
/* enable interrupts */
sc->sc_intr_enable = SOTG_DCINTERRUPT_IEVBUS |
SOTG_DCINTERRUPT_IEBRST | SOTG_DCINTERRUPT_IESUSP;
- SAF1761_WRITE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable);
+ SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable);
/*
* 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 |
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_SET_CLR,
+ SOTG_CTRL_CLR(0xFFFF));
+ SAF1761_WRITE_LE_4(sc, SOTG_CTRL_SET_CLR,
+ SOTG_CTRL_SET(SOTG_CTRL_SW_SEL_HC_DC |
SOTG_CTRL_BDIS_ACON_EN | SOTG_CTRL_SEL_CP_EXT |
- SOTG_CTRL_VBUS_DRV);
+ SOTG_CTRL_VBUS_DRV));
/* disable device address */
- SAF1761_WRITE_1(sc, SOTG_ADDRESS, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_ADDRESS, 0);
- /* enable host controller clock */
- SAF1761_WRITE_4(sc, SOTG_POWER_DOWN, SOTG_POWER_DOWN_HC_CLK_EN);
+ /* enable host controller clock and preserve reserved bits */
+ x = SAF1761_READ_LE_4(sc, SOTG_POWER_DOWN);
+ SAF1761_WRITE_LE_4(sc, SOTG_POWER_DOWN, x | SOTG_POWER_DOWN_HC_CLK_EN);
/* wait 10ms for clock */
usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
/* enable configuration flag */
- SAF1761_WRITE_4(sc, SOTG_CONFIGFLAG, SOTG_CONFIGFLAG_ENABLE);
+ SAF1761_WRITE_LE_4(sc, SOTG_CONFIGFLAG, SOTG_CONFIGFLAG_ENABLE);
/* clear RAM block */
for (x = 0x400; x != 0x10000; x += 4)
- SAF1761_WRITE_4(sc, x, 0);
+ SAF1761_WRITE_LE_4(sc, x, 0);
/* start the HC */
- SAF1761_WRITE_4(sc, SOTG_USBCMD, SOTG_USBCMD_RS);
+ SAF1761_WRITE_LE_4(sc, SOTG_USBCMD, SOTG_USBCMD_RS);
+
+ DPRINTF("USBCMD=0x%08x\n", SAF1761_READ_LE_4(sc, SOTG_USBCMD));
+
+ /* activate all PTDs */
+ SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_LAST_PTD, (1 << 31));
+ SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_LAST_PTD, (1 << 31));
+ SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_LAST_PTD, (1 << 31));
+
+ /* skip no PTDs */
+ SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, 0);
- DPRINTF("USBCMD=0x%08x\n", SAF1761_READ_4(sc, SOTG_USBCMD));
+ /* activate all PTD types */
+ SAF1761_WRITE_LE_4(sc, SOTG_HCBUFFERSTATUS,
+ SOTG_HCBUFFERSTATUS_ISO_BUF_FILL |
+ SOTG_HCBUFFERSTATUS_INT_BUF_FILL |
+ SOTG_HCBUFFERSTATUS_ATL_BUF_FILL);
/* enable HC interrupts */
- SAF1761_WRITE_4(sc, SOTG_HCINTERRUPT_ENABLE,
+ SAF1761_WRITE_LE_4(sc, SOTG_HCINTERRUPT_ENABLE,
SOTG_HCINTERRUPT_OTG_IRQ |
SOTG_HCINTERRUPT_ISO_IRQ |
SOTG_HCINTERRUPT_ALT_IRQ |
@@ -1998,7 +2139,7 @@ saf1761_otg_uninit(struct saf1761_otg_softc *sc)
USB_BUS_LOCK(&sc->sc_bus);
/* disable all interrupts */
- SAF1761_WRITE_2(sc, SOTG_MODE, 0);
+ SAF1761_WRITE_LE_4(sc, SOTG_MODE, 0);
sc->sc_flags.port_powered = 0;
sc->sc_flags.status_vbus = 0;
@@ -2099,7 +2240,7 @@ saf1761_otg_device_isoc_enter(struct usb_xfer *xfer)
/* get the current frame index - we don't need the high bits */
- nframes = SAF1761_READ_2(sc, SOTG_FRAME_NUM);
+ nframes = SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM);
/*
* check if the frame index is within the window where the
@@ -2160,9 +2301,13 @@ static const struct usb_pipe_methods saf1761_otg_device_isoc_methods =
* Simulate a hardware HUB by handling all the necessary requests.
*------------------------------------------------------------------------*/
+#define HSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) }
+
static const struct usb_device_descriptor saf1761_otg_devd = {
.bLength = sizeof(struct usb_device_descriptor),
.bDescriptorType = UDESC_DEVICE,
+ HSETW(.idVendor, 0x04cc),
+ HSETW(.idProduct, 0x1761),
.bcdUSB = {0x00, 0x02},
.bDeviceClass = UDCLASS_HUB,
.bDeviceSubClass = UDSUBCLASS_HUB,
@@ -2215,8 +2360,6 @@ static const struct saf1761_otg_config_desc saf1761_otg_confd = {
},
};
-#define HSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) }
-
static const struct usb_hub_descriptor_min saf1761_otg_hubd = {
.bDescLength = sizeof(saf1761_otg_hubd),
.bDescriptorType = UDESC_HUB,
@@ -2558,27 +2701,27 @@ tr_handle_clear_port_feature_device:
tr_handle_clear_port_feature_host:
DPRINTFN(9, "UR_CLEAR_FEATURE on port %d\n", index);
- temp = SAF1761_READ_4(sc, SOTG_PORTSC1);
+ temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1);
switch (value) {
case UHF_PORT_ENABLE:
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PED);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PED);
break;
case UHF_PORT_SUSPEND:
if ((temp & SOTG_PORTSC1_SUSP) && (!(temp & SOTG_PORTSC1_FPR)))
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_FPR);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_FPR);
/* wait 20ms for resume sequence to complete */
usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50);
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp & ~(SOTG_PORTSC1_SUSP |
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~(SOTG_PORTSC1_SUSP |
SOTG_PORTSC1_FPR | SOTG_PORTSC1_LS /* High Speed */ ));
/* 4ms settle time */
usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 250);
break;
case UHF_PORT_INDICATOR:
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PIC);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PIC);
break;
case UHF_PORT_TEST:
case UHF_C_PORT_ENABLE:
@@ -2588,10 +2731,10 @@ tr_handle_clear_port_feature_host:
/* NOPs */
break;
case UHF_PORT_POWER:
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PP);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PP);
break;
case UHF_C_PORT_CONNECTION:
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_ECSC);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_ECSC);
break;
default:
err = USB_ERR_IOERROR;
@@ -2624,14 +2767,14 @@ tr_handle_set_port_feature_device:
tr_handle_set_port_feature_host:
DPRINTFN(9, "UR_SET_FEATURE on port %d\n", index);
- temp = SAF1761_READ_4(sc, SOTG_PORTSC1);
+ temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1);
switch (value) {
case UHF_PORT_ENABLE:
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PED);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PED);
break;
case UHF_PORT_SUSPEND:
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_SUSP);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_SUSP);
break;
case UHF_PORT_RESET:
DPRINTFN(6, "reset port %d\n", index);
@@ -2639,18 +2782,18 @@ tr_handle_set_port_feature_host:
/* Start reset sequence. */
temp &= ~(SOTG_PORTSC1_PED | SOTG_PORTSC1_PR);
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PR);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PR);
/* Wait for reset to complete. */
usb_pause_mtx(&sc->sc_bus.bus_mtx,
USB_MS_TO_TICKS(usb_port_root_reset_delay));
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp);
/* Wait for HC to complete reset. */
usb_pause_mtx(&sc->sc_bus.bus_mtx, USB_MS_TO_TICKS(2));
- temp = SAF1761_READ_4(sc, SOTG_PORTSC1);
+ temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1);
DPRINTF("After reset, status=0x%08x\n", temp);
if (temp & SOTG_PORTSC1_PR) {
@@ -2660,7 +2803,7 @@ tr_handle_set_port_feature_host:
}
if (!(temp & SOTG_PORTSC1_PED)) {
/* Not a high speed device, give up ownership.*/
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PO);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PO);
break;
}
sc->sc_isreset = 1;
@@ -2668,7 +2811,7 @@ tr_handle_set_port_feature_host:
break;
case UHF_PORT_POWER:
DPRINTFN(3, "set port power %d\n", index);
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PP);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PP);
break;
case UHF_PORT_TEST:
@@ -2677,7 +2820,7 @@ tr_handle_set_port_feature_host:
case UHF_PORT_INDICATOR:
DPRINTFN(3, "set port ind %d\n", index);
- SAF1761_WRITE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PIC);
+ SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PIC);
break;
default:
err = USB_ERR_IOERROR;
@@ -2728,7 +2871,7 @@ tr_handle_get_port_status_device:
tr_handle_get_port_status_host:
- temp = SAF1761_READ_4(sc, SOTG_PORTSC1);
+ temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1);
DPRINTFN(9, "UR_GET_PORT_STATUS on port %d = 0x%08x\n", index, temp);
@@ -2847,7 +2990,7 @@ saf1761_otg_xfer_setup(struct usb_setup_params *parm)
case USB_SPEED_LOW:
/* check if root HUB port is running High Speed */
if (parm->udev->parent_hs_hub != NULL) {
- dw1 |= (1 << 14);
+ dw1 |= SOTG_PTD_DW1_ENABLE_SPLIT;
dw1 |= (parm->udev->hs_port_no << 18);
dw1 |= (parm->udev->hs_hub_addr << 25);
if (parm->udev->speed == USB_SPEED_LOW)
@@ -2877,9 +3020,9 @@ saf1761_otg_xfer_setup(struct usb_setup_params *parm)
td->uframe = 0;
if (ep_type == UE_INTERRUPT) {
if (xfer->interval > 32)
- td->interval = 32 / 2;
+ td->interval = (32 / 2) << 3;
else
- td->interval = xfer->interval / 2;
+ td->interval = (xfer->interval / 2) << 3;
} else {
td->interval = 0;
}
diff --git a/sys/dev/usb/controller/saf1761_otg.h b/sys/dev/usb/controller/saf1761_otg.h
index 9b19d3c965c3..6b7697255ea6 100644
--- a/sys/dev/usb/controller/saf1761_otg.h
+++ b/sys/dev/usb/controller/saf1761_otg.h
@@ -32,7 +32,7 @@
#ifndef _SAF1761_OTG_H_
#define _SAF1761_OTG_H_
-#define SOTG_MAX_DEVICES (USB_MIN_DEVICES + 1)
+#define SOTG_MAX_DEVICES MIN(USB_MAX_DEVICES, 32)
#define SOTG_FS_MAX_PACKET_SIZE 64
#define SOTG_HS_MAX_PACKET_SIZE 512
#define SOTG_NUM_PORTS 2 /* one Device and one Host port */
@@ -40,28 +40,26 @@
#define SOTG_DEVICE_PORT_NUM 2
#define SOTG_HOST_CHANNEL_MAX (3 * 32)
-/* Macros used for reading and writing registers */
+/* Macros used for reading and writing little endian registers */
-#define SAF1761_READ_1(sc, reg) \
- bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg))
-#define SAF1761_READ_2(sc, reg) ({ uint16_t _temp; \
- _temp = bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg)); \
- le16toh(_temp); })
-#define SAF1761_READ_4(sc, reg) ({ uint32_t _temp; \
+#define SAF1761_READ_LE_4(sc, reg) ({ uint32_t _temp; \
_temp = bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg)); \
le32toh(_temp); })
-#define SAF1761_WRITE_1(sc, reg, data) \
- bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg), data)
-#define SAF1761_WRITE_2(sc, reg, data) do { \
- uint16_t _temp = (data); \
- bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg), htole16(_temp)); \
-} while (0)
-#define SAF1761_WRITE_4(sc, reg, data) do { \
+#define SAF1761_WRITE_LE_4(sc, reg, data) do { \
uint32_t _temp = (data); \
bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg), htole32(_temp)); \
} while (0)
+/* 90ns delay macro */
+
+#define SAF1761_90NS_DELAY(sc) do { \
+ (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \
+ (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \
+ (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \
+ (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \
+} while (0)
+
struct saf1761_otg_softc;
struct saf1761_otg_td;
@@ -147,7 +145,8 @@ struct saf1761_otg_softc {
uint32_t sc_intr_enable; /* enabled interrupts */
uint32_t sc_hw_mode; /* hardware mode */
- uint8_t sc_bounce_buffer[1024] __aligned(4);
+ uint32_t sc_bounce_buffer[1024 / 4];
+
uint8_t sc_rt_addr; /* root HUB address */
uint8_t sc_dv_addr; /* device address */
uint8_t sc_conf; /* root HUB config */
diff --git a/sys/dev/usb/controller/saf1761_otg_reg.h b/sys/dev/usb/controller/saf1761_otg_reg.h
index 6e104bcf1642..bfed688bf28b 100644
--- a/sys/dev/usb/controller/saf1761_otg_reg.h
+++ b/sys/dev/usb/controller/saf1761_otg_reg.h
@@ -34,10 +34,12 @@
/* Global registers */
-#define SOTG_VEND_ID 0x370
-#define SOTG_PROD_ID 0x372
-#define SOTG_CTRL_SET 0x374
-#define SOTG_CTRL_CLR 0x376
+#define SOTG_VEND_PROD_ID 0x370
+#define SOTG_VEND_ID(x) ((x) & 0xFFFF)
+#define SOTG_PROD_ID(x) (((x) >> 16) & 0xFFFF)
+#define SOTG_CTRL_SET_CLR 0x374
+#define SOTG_CTRL_SET(x) ((x) & 0xFFFF)
+#define SOTG_CTRL_CLR(x) (((x) << 16) & 0xFFFF0000)
#define SOTG_CTRL_OTG_DISABLE (1 << 10)
#define SOTG_CTRL_OTG_SE0_EN (1 << 9)
#define SOTG_CTRL_BDIS_ACON_EN (1 << 8)
@@ -57,12 +59,15 @@
#define SOTG_STATUS_DP_SRP (1 << 2)
#define SOTG_STATUS_A_B_SESS_VLD (1 << 1)
#define SOTG_STATUS_VBUS_VLD (1 << 0)
-#define SOTG_IRQ_LATCH_SET 0x37C
-#define SOTG_IRQ_LATCH_CLR 0x37E
-#define SOTG_IRQ_ENABLE_SET 0x380
-#define SOTG_IRQ_ENABLE_CLR 0x382
-#define SOTG_IRQ_RISE_SET 0x384
-#define SOTG_IRQ_RISE_CLR 0x386
+#define SOTG_IRQ_LATCH_SET_CLR 0x37C
+#define SOTG_IRQ_LATCH_SET(x) ((x) & 0xFFFF)
+#define SOTG_IRQ_LATCH_CLR(x) (((x) << 16) & 0xFFFF0000)
+#define SOTG_IRQ_ENABLE_SET_CLR 0x380
+#define SOTG_IRQ_ENABLE_SET(x) ((x) & 0xFFFF)
+#define SOTG_IRQ_ENABLE_CLR(x) (((x) << 16) & 0xFFFF0000)
+#define SOTG_IRQ_RISE_SET_CLR 0x384
+#define SOTG_IRQ_RISE_SET(x) ((x) & 0xFFFF)
+#define SOTG_IRQ_RISE_CLR(x) (((x) << 16) & 0xFFFF0000)
#define SOTG_IRQ_OTG_TMR_TIMEOUT (1 << 9)
#define SOTG_IRQ_B_SE0_SRP (1 << 8)
#define SOTG_IRQ_B_SESS_END (1 << 7)
@@ -73,10 +78,12 @@
#define SOTG_IRQ_DP_SRP (1 << 2)
#define SOTG_IRQ_A_B_SESS_VLD (1 << 1)
#define SOTG_IRQ_VBUS_VLD (1 << 0)
-#define SOTG_TIMER_LOW_SET 0x388
-#define SOTG_TIMER_LOW_CLR 0x38A
-#define SOTG_TIMER_HIGH_SET 0x38C
-#define SOTG_TIMER_HIGH_CLR 0x38E
+#define SOTG_TIMER_LOW_SET_CLR 0x388
+#define SOTG_TIMER_LOW_SET(x) ((x) & 0xFFFF)
+#define SOTG_TIMER_LOW_CLR(x) (((x) << 16) & 0xFFFF0000)
+#define SOTG_TIMER_HIGH_SET_CLR 0x38C
+#define SOTG_TIMER_HIGH_SET(x) ((x) & 0xFFFF)
+#define SOTG_TIMER_HIGH_CLR(x) (((x) << 16) & 0xFFFF0000)
#define SOTG_TIMER_START_TMR (1U << 15)
#define SOTG_MEMORY_REG 0x33c
@@ -94,13 +101,12 @@
#define SOTG_MODE_GLINTENA (1 << 3)
#define SOTG_MODE_WKUPCS (1 << 2)
#define SOTG_INTERRUPT_CFG 0x210
+#define SOTG_INTERRUPT_CFG_DEBUG_SET (1 << 16)
#define SOTG_INTERRUPT_CFG_CDBGMOD (3 << 6)
#define SOTG_INTERRUPT_CFG_DDBGMODIN (3 << 4)
#define SOTG_INTERRUPT_CFG_DDBGMODOUT (3 << 2)
#define SOTG_INTERRUPT_CFG_INTLVL (1 << 1)
#define SOTG_INTERRUPT_CFG_INTPOL (1 << 0)
-#define SOTG_DEBUG 0x212
-#define SOTG_DEBUG_SET (1 << 0)
#define SOTG_DCINTERRUPT_EN 0x214
#define SOTG_HW_MODE_CTRL 0x300
#define SOTG_HW_MODE_CTRL_ALL_ATX_RESET (1 << 31)
@@ -129,8 +135,8 @@
#define SOTG_CTRL_FUNC_STALL (1 << 0)
#define SOTG_DATA_PORT 0x220
#define SOTG_BUF_LENGTH 0x21C
-#define SOTG_DCBUFFERSTATUS 0x21E
-#define SOTG_DCBUFFERSTATUS_FILLED_MASK (3 << 0)
+#define SOTG_BUF_LENGTH_BUFLEN_MASK 0xFFFF
+#define SOTG_BUF_LENGTH_FILLED_MASK (3 << 16)
#define SOTG_EP_MAXPACKET 0x204
#define SOTG_EP_TYPE 0x208
#define SOTG_EP_TYPE_NOEMPPKT (1 << 4)
@@ -176,6 +182,7 @@
/* Host controller specific registers */
+#define SOTG_FRINDEX 0x002c
#define SOTG_CONFIGFLAG 0x0060
#define SOTG_CONFIGFLAG_ENABLE (1 << 0)
#define SOTG_PORTSC1 0x0064
@@ -189,25 +196,26 @@
#define SOTG_PORTSC1_PED (1 << 2)
#define SOTG_PORTSC1_ECSC (1 << 1)
#define SOTG_PORTSC1_ECCS (1 << 0)
-#define SOTG_PDT_DW0 0
-#define SOTG_PDT_DW0_VALID 1U
-#define SOTG_PDT_DW1 4
-#define SOTG_PDT_DW2 8
-#define SOTG_PDT_DW3 12
-#define SOTG_PDT_DW3_ACTIVE (1U << 31)
-#define SOTG_PDT_DW3_HALTED (1U << 30)
-#define SOTG_PDT_DW3_ERRORS (3U << 28)
-#define SOTG_PDT_DW3_CERR (3U << 23)
-#define SOTG_PDT_DW3_XFER_COUNT 0x7FFF
-#define SOTG_PDT_DW4 16
-#define SOTG_PDT_DW5 20
-#define SOTG_PDT_DW6 24
-#define SOTG_PDT_DW7 28
+#define SOTG_PTD_DW0 0
+#define SOTG_PTD_DW0_VALID 1U
+#define SOTG_PTD_DW1 4
+#define SOTG_PTD_DW1_ENABLE_SPLIT (1 << 14)
+#define SOTG_PTD_DW2 8
+#define SOTG_PTD_DW3 12
+#define SOTG_PTD_DW3_ACTIVE (1U << 31)
+#define SOTG_PTD_DW3_HALTED (1U << 30)
+#define SOTG_PTD_DW3_ERRORS (3U << 28)
+#define SOTG_PTD_DW3_CERR (3U << 23)
+#define SOTG_PTD_DW3_XFER_COUNT 0x7FFF
+#define SOTG_PTD_DW4 16
+#define SOTG_PTD_DW5 20
+#define SOTG_PTD_DW6 24
+#define SOTG_PTD_DW7 28
#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_PDT(x) (0x400 + ((x) * 32))
+#define SOTG_ASYNC_PTD(x) (0xC00 + ((x) * 32))
+#define SOTG_INTR_PTD(x) (0x800 + ((x) * 32))
+#define SOTG_ISOC_PTD(x) (0x400 + ((x) * 32))
+#define SOTG_PTD(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)
@@ -237,5 +245,15 @@
#define SOTG_HCINTERRUPT_DMAEOTINT (1 << 3)
#define SOTG_HCINTERRUPT_SOFITLINT (1 << 1)
#define SOTG_HCINTERRUPT_ENABLE 0x314
+#define SOTG_ATL_PTD_SKIP_PTD 0x154
+#define SOTG_ATL_PTD_LAST_PTD 0x158
+#define SOTG_INT_PTD_SKIP_PTD 0x144
+#define SOTG_INT_PTD_LAST_PTD 0x148
+#define SOTG_ISO_PTD_SKIP_PTD 0x134
+#define SOTG_ISO_PTD_LAST_PTD 0x138
+#define SOTG_HCBUFFERSTATUS 0x334
+#define SOTG_HCBUFFERSTATUS_ISO_BUF_FILL (1 << 2)
+#define SOTG_HCBUFFERSTATUS_INT_BUF_FILL (1 << 1)
+#define SOTG_HCBUFFERSTATUS_ATL_BUF_FILL (1 << 0)
#endif /* _SAF1761_OTG_REG_H_ */