Fixes for ISP/SAF1761 host mode:
- Make the USB hardware skip PTDs which are not allocated. - Peek host memory twice. Sometimes the PTD status is incorrectly returned as zero. - Ensure the host channel is always freed when software TD is completing. - Add correct configuration of interrupt polarity and type. - Set CERR to 2 for asynchronous traffic to avoid having to reactivate the PTD when a NAK token is received. - Fix detection of STALL PID. Sponsored by: DARPA, AFRL
This commit is contained in:
parent
bdec45e2bc
commit
4272b84663
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=266812
@ -252,25 +252,24 @@ saf1761_host_channel_free(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
if (td->channel >= SOTG_HOST_CHANNEL_MAX)
|
||||
return;
|
||||
|
||||
/* disable channel */
|
||||
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:
|
||||
x = td->channel - 32;
|
||||
sc->sc_host_intr_map &= ~(1 << x);
|
||||
td->channel = SOTG_HOST_CHANNEL_MAX;
|
||||
sc->sc_host_intr_map &= ~(1 << x);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, ~sc->sc_host_intr_map);
|
||||
break;
|
||||
case UE_ISOCHRONOUS:
|
||||
x = td->channel;
|
||||
sc->sc_host_isoc_map &= ~(1 << x);
|
||||
td->channel = SOTG_HOST_CHANNEL_MAX;
|
||||
sc->sc_host_isoc_map &= ~(1 << x);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map);
|
||||
break;
|
||||
default:
|
||||
x = td->channel - 64;
|
||||
sc->sc_host_async_map &= ~(1 << x);
|
||||
td->channel = SOTG_HOST_CHANNEL_MAX;
|
||||
sc->sc_host_async_map &= ~(1 << x);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -401,19 +400,16 @@ saf1761_host_setup_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
|
||||
pdt_addr = SOTG_PTD(td->channel);
|
||||
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
if (status == 0)
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
|
||||
DPRINTFN(5, "STATUS=0x%08x\n", status);
|
||||
|
||||
if (status & SOTG_PTD_DW3_ACTIVE) {
|
||||
goto busy;
|
||||
} else if (status & SOTG_PTD_DW3_HALTED) {
|
||||
td->error_stall = 1;
|
||||
td->error_any = 1;
|
||||
} else if (status & SOTG_PTD_DW3_ERRORS) {
|
||||
td->error_any = 1;
|
||||
}
|
||||
count = (status & SOTG_PTD_DW3_XFER_COUNT);
|
||||
|
||||
saf1761_host_channel_free(sc, td);
|
||||
goto complete;
|
||||
}
|
||||
if (saf1761_host_channel_alloc(sc, td))
|
||||
@ -435,7 +431,7 @@ saf1761_host_setup_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0);
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0);
|
||||
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR_3;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
|
||||
|
||||
temp = SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8;
|
||||
@ -450,10 +446,14 @@ saf1761_host_setup_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
|
||||
SOTG_PTD_DW0_VALID;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
|
||||
|
||||
/* activate PTD */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map);
|
||||
|
||||
td->toggle = 1;
|
||||
busy:
|
||||
return (1); /* busy */
|
||||
complete:
|
||||
saf1761_host_channel_free(sc, td);
|
||||
return (0); /* complete */
|
||||
}
|
||||
|
||||
@ -471,15 +471,16 @@ saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
pdt_addr = SOTG_PTD(td->channel);
|
||||
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
if (status == 0)
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
|
||||
DPRINTFN(5, "STATUS=0x%08x\n", status);
|
||||
|
||||
if (status & SOTG_PTD_DW3_ACTIVE) {
|
||||
goto busy;
|
||||
} else if (status & SOTG_PTD_DW3_HALTED) {
|
||||
td->error_stall = 1;
|
||||
td->error_any = 1;
|
||||
goto complete;
|
||||
} else if (status & SOTG_PTD_DW3_ERRORS) {
|
||||
if (!(status & SOTG_PTD_DW3_ERRORS))
|
||||
td->error_stall = 1;
|
||||
td->error_any = 1;
|
||||
goto complete;
|
||||
}
|
||||
@ -509,14 +510,13 @@ saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
|
||||
saf1761_read_host_memory(sc, td, count);
|
||||
|
||||
saf1761_host_channel_free(sc, td);
|
||||
|
||||
/* check if we are complete */
|
||||
if ((td->remainder == 0) || got_short) {
|
||||
if (td->short_pkt)
|
||||
goto complete;
|
||||
/* else need to receive a zero length packet */
|
||||
}
|
||||
saf1761_host_channel_free(sc, td);
|
||||
}
|
||||
if (saf1761_host_channel_alloc(sc, td))
|
||||
goto busy;
|
||||
@ -536,10 +536,11 @@ saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0);
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0);
|
||||
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) |
|
||||
SOTG_PTD_DW3_CERR_2;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
|
||||
|
||||
temp = SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8;
|
||||
temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8);
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp);
|
||||
|
||||
temp = td->dw1_value | (1 << 10) /* IN-PID */ | (td->ep_index >> 1);
|
||||
@ -550,9 +551,13 @@ saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
(td->max_packet_size << 3) /* transfer count */ |
|
||||
SOTG_PTD_DW0_VALID;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
|
||||
|
||||
/* activate PTD */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map);
|
||||
busy:
|
||||
return (1); /* busy */
|
||||
complete:
|
||||
saf1761_host_channel_free(sc, td);
|
||||
return (0); /* complete */
|
||||
}
|
||||
|
||||
@ -569,25 +574,26 @@ saf1761_host_bulk_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
pdt_addr = SOTG_PTD(td->channel);
|
||||
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
if (status == 0)
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
|
||||
DPRINTFN(5, "STATUS=0x%08x\n", status);
|
||||
|
||||
if (status & SOTG_PTD_DW3_ACTIVE) {
|
||||
goto busy;
|
||||
} else if (status & SOTG_PTD_DW3_HALTED) {
|
||||
td->error_stall = 1;
|
||||
td->error_any = 1;
|
||||
} else if (status & SOTG_PTD_DW3_ERRORS) {
|
||||
if (!(status & SOTG_PTD_DW3_ERRORS))
|
||||
td->error_stall = 1;
|
||||
td->error_any = 1;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
saf1761_host_channel_free(sc, td);
|
||||
|
||||
/* check remainder */
|
||||
if (td->remainder == 0) {
|
||||
if (td->short_pkt)
|
||||
goto complete;
|
||||
/* else we need to transmit a short packet */
|
||||
}
|
||||
saf1761_host_channel_free(sc, td);
|
||||
}
|
||||
if (saf1761_host_channel_alloc(sc, td))
|
||||
goto busy;
|
||||
@ -616,10 +622,11 @@ saf1761_host_bulk_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0);
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0);
|
||||
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) |
|
||||
SOTG_PTD_DW3_CERR_2;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
|
||||
|
||||
temp = SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8;
|
||||
temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8);
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp);
|
||||
|
||||
temp = td->dw1_value | (0 << 10) /* OUT-PID */ | (td->ep_index >> 1);
|
||||
@ -631,10 +638,14 @@ saf1761_host_bulk_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
SOTG_PTD_DW0_VALID;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
|
||||
|
||||
/* activate PTD */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map);
|
||||
|
||||
td->toggle ^= 1;
|
||||
busy:
|
||||
return (1); /* busy */
|
||||
complete:
|
||||
saf1761_host_channel_free(sc, td);
|
||||
return (0); /* complete */
|
||||
}
|
||||
|
||||
@ -652,16 +663,19 @@ saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
pdt_addr = SOTG_PTD(td->channel);
|
||||
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
if (status == 0)
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
|
||||
DPRINTFN(5, "STATUS=0x%08x\n", status);
|
||||
|
||||
if (status & SOTG_PTD_DW3_ACTIVE) {
|
||||
goto busy;
|
||||
} else if (status & SOTG_PTD_DW3_HALTED) {
|
||||
td->error_stall = 1;
|
||||
if (!(status & SOTG_PTD_DW3_ERRORS))
|
||||
td->error_stall = 1;
|
||||
td->error_any = 1;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
count = (status & SOTG_PTD_DW3_XFER_COUNT);
|
||||
got_short = 0;
|
||||
|
||||
@ -688,14 +702,13 @@ saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
|
||||
saf1761_read_host_memory(sc, td, count);
|
||||
|
||||
saf1761_host_channel_free(sc, td);
|
||||
|
||||
/* check if we are complete */
|
||||
if ((td->remainder == 0) || got_short) {
|
||||
if (td->short_pkt)
|
||||
goto complete;
|
||||
/* else need to receive a zero length packet */
|
||||
}
|
||||
saf1761_host_channel_free(sc, td);
|
||||
}
|
||||
if (saf1761_host_channel_alloc(sc, td))
|
||||
goto busy;
|
||||
@ -719,7 +732,7 @@ saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
temp = (1U << td->uframe); /* start split */
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp);
|
||||
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR_3;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
|
||||
|
||||
temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | (td->interval & 0xF8);
|
||||
@ -733,9 +746,13 @@ saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
(td->max_packet_size << 3) /* transfer count */ |
|
||||
SOTG_PTD_DW0_VALID;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
|
||||
|
||||
/* activate PTD */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, ~sc->sc_host_intr_map);
|
||||
busy:
|
||||
return (1); /* busy */
|
||||
complete:
|
||||
saf1761_host_channel_free(sc, td);
|
||||
return (0); /* complete */
|
||||
}
|
||||
|
||||
@ -752,23 +769,27 @@ saf1761_host_intr_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
pdt_addr = SOTG_PTD(td->channel);
|
||||
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
if (status == 0)
|
||||
status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3);
|
||||
|
||||
DPRINTFN(5, "STATUS=0x%08x\n", status);
|
||||
|
||||
if (status & SOTG_PTD_DW3_ACTIVE) {
|
||||
goto busy;
|
||||
} else if (status & SOTG_PTD_DW3_HALTED) {
|
||||
td->error_stall = 1;
|
||||
if (!(status & SOTG_PTD_DW3_ERRORS))
|
||||
td->error_stall = 1;
|
||||
td->error_any = 1;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
saf1761_host_channel_free(sc, td);
|
||||
|
||||
/* check remainder */
|
||||
if (td->remainder == 0) {
|
||||
if (td->short_pkt)
|
||||
goto complete;
|
||||
/* else we need to transmit a short packet */
|
||||
}
|
||||
saf1761_host_channel_free(sc, td);
|
||||
}
|
||||
if (saf1761_host_channel_alloc(sc, td))
|
||||
goto busy;
|
||||
@ -801,7 +822,7 @@ saf1761_host_intr_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
temp = (1U << td->uframe); /* start split */
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp);
|
||||
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR;
|
||||
temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR_3;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp);
|
||||
|
||||
temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | (td->interval & 0xF8);
|
||||
@ -816,22 +837,32 @@ saf1761_host_intr_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *t
|
||||
SOTG_PTD_DW0_VALID;
|
||||
SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp);
|
||||
|
||||
/* activate PTD */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, ~sc->sc_host_intr_map);
|
||||
|
||||
td->toggle ^= 1;
|
||||
busy:
|
||||
return (1); /* busy */
|
||||
complete:
|
||||
saf1761_host_channel_free(sc, td);
|
||||
return (0); /* complete */
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
saf1761_host_isoc_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
|
||||
{
|
||||
/* activate PTD */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map);
|
||||
|
||||
return (1); /* busy */
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
saf1761_host_isoc_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td)
|
||||
{
|
||||
/* activate PTD */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map);
|
||||
|
||||
return (1); /* busy */
|
||||
}
|
||||
|
||||
@ -1319,10 +1350,13 @@ saf1761_otg_interrupt(struct saf1761_otg_softc *sc)
|
||||
SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM),
|
||||
SAF1761_READ_LE_4(sc, SOTG_FRINDEX));
|
||||
|
||||
(void) SAF1761_READ_LE_4(sc, SOTG_ATL_PTD_DONE_PTD);
|
||||
(void) SAF1761_READ_LE_4(sc, SOTG_INT_PTD_DONE_PTD);
|
||||
(void) SAF1761_READ_LE_4(sc, SOTG_ISO_PTD_DONE_PTD);
|
||||
|
||||
/* update VBUS and ID bits, if any */
|
||||
if (status & SOTG_DCINTERRUPT_IEVBUS) {
|
||||
if (status & SOTG_DCINTERRUPT_IEVBUS)
|
||||
saf1761_otg_update_vbus(sc);
|
||||
}
|
||||
|
||||
if (status & SOTG_DCINTERRUPT_IEBRST) {
|
||||
/* unlock device */
|
||||
@ -1431,7 +1465,8 @@ saf1761_otg_setup_standard_chain(struct usb_xfer *xfer)
|
||||
temp.td = NULL;
|
||||
temp.td_next = xfer->td_start[0];
|
||||
temp.offset = 0;
|
||||
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
|
||||
temp.setup_alt_next = xfer->flags_int.short_frames_ok ||
|
||||
xfer->flags_int.isochronous_xfr;
|
||||
temp.did_stall = !xfer->flags_int.control_stall;
|
||||
|
||||
is_host = (xfer->xroot->udev->flags.usb_mode == USB_MODE_HOST);
|
||||
@ -1732,7 +1767,8 @@ saf1761_otg_standard_done_sub(struct usb_xfer *xfer)
|
||||
}
|
||||
/* Check for short transfer */
|
||||
if (len > 0) {
|
||||
if (xfer->flags_int.short_frames_ok) {
|
||||
if (xfer->flags_int.short_frames_ok ||
|
||||
xfer->flags_int.isochronous_xfr) {
|
||||
/* follow alt next */
|
||||
if (td->alt_next) {
|
||||
td = td->obj_next;
|
||||
@ -2048,12 +2084,13 @@ saf1761_otg_init(struct saf1761_otg_softc *sc)
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_MODE, SOTG_MODE_GLINTENA |
|
||||
SOTG_MODE_CLKAON | SOTG_MODE_WKUPCS);
|
||||
|
||||
sc->sc_interrupt_cfg |=
|
||||
SOTG_INTERRUPT_CFG_CDBGMOD |
|
||||
SOTG_INTERRUPT_CFG_DDBGMODIN |
|
||||
SOTG_INTERRUPT_CFG_DDBGMODOUT;
|
||||
|
||||
/* set default values */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INTERRUPT_CFG,
|
||||
SOTG_INTERRUPT_CFG_CDBGMOD |
|
||||
SOTG_INTERRUPT_CFG_DDBGMODIN |
|
||||
SOTG_INTERRUPT_CFG_DDBGMODOUT |
|
||||
sc->sc_interrupt_cfg);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INTERRUPT_CFG, sc->sc_interrupt_cfg);
|
||||
|
||||
/* enable VBUS and ID interrupt */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_IRQ_ENABLE_SET_CLR,
|
||||
@ -2099,15 +2136,15 @@ saf1761_otg_init(struct saf1761_otg_softc *sc)
|
||||
|
||||
DPRINTF("USBCMD=0x%08x\n", SAF1761_READ_LE_4(sc, SOTG_USBCMD));
|
||||
|
||||
/* activate all PTDs */
|
||||
/* make HC scan 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);
|
||||
/* skip all PTDs by default */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, -1U);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, -1U);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, -1U);
|
||||
|
||||
/* activate all PTD types */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_HCBUFFERSTATUS,
|
||||
@ -2115,6 +2152,16 @@ saf1761_otg_init(struct saf1761_otg_softc *sc)
|
||||
SOTG_HCBUFFERSTATUS_INT_BUF_FILL |
|
||||
SOTG_HCBUFFERSTATUS_ATL_BUF_FILL);
|
||||
|
||||
/* we don't use the AND mask */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ISO_IRQ_MASK_AND, 0);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INT_IRQ_MASK_AND, 0);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ATL_IRQ_MASK_AND, 0);
|
||||
|
||||
/* enable all PTD OR interrupts by default */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ISO_IRQ_MASK_OR, -1U);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_INT_IRQ_MASK_OR, -1U);
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_ATL_IRQ_MASK_OR, -1U);
|
||||
|
||||
/* enable HC interrupts */
|
||||
SAF1761_WRITE_LE_4(sc, SOTG_HCINTERRUPT_ENABLE,
|
||||
SOTG_HCINTERRUPT_OTG_IRQ |
|
||||
|
@ -160,12 +160,14 @@ saf1761_otg_fdt_attach(device_t dev)
|
||||
if (OF_getprop(ofw_bus_get_node(dev), "int-polarity",
|
||||
¶m, sizeof(param)) > 0) {
|
||||
sc->sc_interrupt_cfg |= SOTG_INTERRUPT_CFG_INTPOL;
|
||||
sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_INTR_POL;
|
||||
}
|
||||
|
||||
/* get IRQ level triggering */
|
||||
if (OF_getprop(ofw_bus_get_node(dev), "int-level",
|
||||
¶m, sizeof(param)) > 0) {
|
||||
sc->sc_interrupt_cfg |= SOTG_INTERRUPT_CFG_INTLVL;
|
||||
sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_INTR_LEVEL;
|
||||
}
|
||||
|
||||
/* initialise some bus fields */
|
||||
@ -182,23 +184,30 @@ saf1761_otg_fdt_attach(device_t dev)
|
||||
sc->sc_io_res =
|
||||
bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
|
||||
if (!sc->sc_io_res) {
|
||||
if (sc->sc_io_res == NULL)
|
||||
goto error;
|
||||
}
|
||||
|
||||
sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
|
||||
sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
|
||||
sc->sc_io_size = rman_get_size(sc->sc_io_res);
|
||||
|
||||
rid = 0;
|
||||
/* try to allocate the HC interrupt first */
|
||||
rid = 1;
|
||||
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
if (sc->sc_irq_res == NULL) {
|
||||
goto error;
|
||||
/* try to allocate a common IRQ second */
|
||||
rid = 0;
|
||||
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
if (sc->sc_irq_res == NULL)
|
||||
goto error;
|
||||
}
|
||||
|
||||
sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
|
||||
if (!(sc->sc_bus.bdev)) {
|
||||
if (sc->sc_bus.bdev == NULL)
|
||||
goto error;
|
||||
}
|
||||
|
||||
device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
|
||||
|
||||
err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
|
@ -84,7 +84,7 @@
|
||||
#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_TIMER_HIGH_START (1U << 15)
|
||||
#define SOTG_MEMORY_REG 0x33c
|
||||
|
||||
/* Peripheral controller specific registers */
|
||||
@ -102,9 +102,9 @@
|
||||
#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_CDBGMOD (1 << 6) /* ACK only */
|
||||
#define SOTG_INTERRUPT_CFG_DDBGMODIN (1 << 4) /* ACK only */
|
||||
#define SOTG_INTERRUPT_CFG_DDBGMODOUT (1 << 2) /* ACK and NYET only */
|
||||
#define SOTG_INTERRUPT_CFG_INTLVL (1 << 1)
|
||||
#define SOTG_INTERRUPT_CFG_INTPOL (1 << 0)
|
||||
#define SOTG_DCINTERRUPT_EN 0x214
|
||||
@ -201,11 +201,15 @@
|
||||
#define SOTG_PTD_DW1 4
|
||||
#define SOTG_PTD_DW1_ENABLE_SPLIT (1 << 14)
|
||||
#define SOTG_PTD_DW2 8
|
||||
#define SOTG_PTD_DW2_RL (0xf << 25)
|
||||
#define SOTG_PTD_DW3 12
|
||||
#define SOTG_PTD_DW3_NRL (0xf << 19)
|
||||
#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_CERR_3 (3U << 23)
|
||||
#define SOTG_PTD_DW3_CERR_2 (2U << 23) /* infinite NAKs */
|
||||
#define SOTG_PTD_DW3_CERR_1 (1U << 23)
|
||||
#define SOTG_PTD_DW3_XFER_COUNT 0x7FFF
|
||||
#define SOTG_PTD_DW4 16
|
||||
#define SOTG_PTD_DW5 20
|
||||
@ -245,15 +249,24 @@
|
||||
#define SOTG_HCINTERRUPT_DMAEOTINT (1 << 3)
|
||||
#define SOTG_HCINTERRUPT_SOFITLINT (1 << 1)
|
||||
#define SOTG_HCINTERRUPT_ENABLE 0x314
|
||||
#define SOTG_ATL_PTD_DONE_PTD 0x150
|
||||
#define SOTG_ATL_PTD_SKIP_PTD 0x154
|
||||
#define SOTG_ATL_PTD_LAST_PTD 0x158
|
||||
#define SOTG_INT_PTD_DONE_PTD 0x140
|
||||
#define SOTG_INT_PTD_SKIP_PTD 0x144
|
||||
#define SOTG_INT_PTD_LAST_PTD 0x148
|
||||
#define SOTG_ISO_PTD_DONE_PTD 0x130
|
||||
#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)
|
||||
#define SOTG_ISO_IRQ_MASK_OR 0x318
|
||||
#define SOTG_INT_IRQ_MASK_OR 0x31C
|
||||
#define SOTG_ATL_IRQ_MASK_OR 0x320
|
||||
#define SOTG_ISO_IRQ_MASK_AND 0x324
|
||||
#define SOTG_INT_IRQ_MASK_AND 0x328
|
||||
#define SOTG_ATL_IRQ_MASK_AND 0x32C
|
||||
|
||||
#endif /* _SAF1761_OTG_REG_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user