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)
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to