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
This commit is contained in:
Hans Petter Selasky 2014-05-20 14:15:03 +00:00
parent 7243077c9d
commit 6804df87a9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=266467
2 changed files with 109 additions and 55 deletions

View File

@ -227,7 +227,7 @@ saf1761_host_channel_alloc(struct saf1761_otg_softc *sc, struct saf1761_otg_td *
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 saf1761_otg_softc *sc, struct saf1761_otg_td *
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_otg_softc *sc, struct saf1761_otg_td *t
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_otg_softc *sc, struct saf1761_otg_td *t
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_otg_softc *sc, struct saf1761_otg_td *t
}
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_softc *sc, struct saf1761_otg_td *td)
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_softc *sc, struct saf1761_otg_td *td)
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_otg_softc *sc, struct saf1761_otg_td *t
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_otg_softc *sc, struct saf1761_otg_td *t
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_otg_softc *sc, struct saf1761_otg_td *t
/* 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_otg_softc *sc, struct saf1761_otg_td *t
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_otg_softc *sc, struct saf1761_otg_td *t
}
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_otg_softc *sc, struct saf1761_otg_td *t
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_otg_softc *sc, uint8_t addr)
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 saf1761_otg_softc *sc, void *buf, uint32_t len
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_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);
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_softc *sc)
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_softc *sc)
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_softc *sc)
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_softc *sc)
/* 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 @@ saf1761_otg_roothub_exec(struct usb_device *udev,
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)

View File

@ -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)