On 06/27/13 02:53, Oleksandr Tymoshenko wrote:

On 2013-04-07, at 12:04 AM, Hans Petter Selasky <h...@bitfrost.no> wrote:

On 04/06/13 22:50, Oleksandr Tymoshenko wrote:

This is first iteration of Host Mode support for Mentor Graphics
OTG USB controller. I tested it by building kernel with USB memory
stick mounted as /usr/obj, resulting kernel was bootable and worked fine.
I reused some ideas (mostly for channel-management) from
DWT OTG driver.

Some pieces are still missing:
- Support for SPLIT transactions, I don not have high speed hub
     right now to test it, but implementing it should be really
- Isochronous transfers. I do not have hardware to test this. Does
     anybody have any suggestion about simple use case?
- Control Data OUT transaction
- Wrapper for atmel HW has not ben synced with new core logic requirements

Please review and test. I tested it only with gcc-built kernel/world.
Now when
first iteration is finished I'm going to update all my boards to new
world order
(clang/EABI) and re-test this stuff.



Looks like you've got the grasp of the USB controller stuff :-)

Some comments:

1) Use DPRINTFN(-1, ...) instead of printf() for all printf() that are not part 
of boot dmesg.

+                               break;
+                       default:
+                               td->transfer_type = 0;
+                               printf("Invalid USB speed: %d\n", speed);
+                               break;
+               }

2) You should implement if HOST mode, support for SUSPEND and RESUME. See EHCI 
driver. Basically what you need is:

a) USB transfers are stopped/paused. I know there is a hack you need if the 
host transfer cancel hangs, and that is to write a dummy device address and 
wait for the USB transfer to error out after 250 us max.

b) switch on USB suspend signalling.

At resume:

c) do resume signalling, similar to EHCI/UHCI I think.

d) switch on channel tokens.

        case UHF_PORT_SUSPEND:
+               if (sc->sc_mode == MUSB2_HOST_MODE)
+                       printf("TODO: Set UHF_PORT_SUSPEND\n");
+               break;

3) Make sure that channels are not generating tokens if they are aborted / 
cancelled / timedout. This can not be verified using a USB mass storage device. 
Verify this by connecting a USB serial adapter. Try to open/close /dev/cuaU0. 
Make sure it does not loose any bytes and that channel cancel does not hang 


Thanks for review. Took  me quite some time to get back
to the driver but here is updated version that addresses some
of the issues you've mentioned:

It fixes several bugs, adds proper SPLIT transactions support and
suspend/resume signalling.  I tested it with urtwn-based WiFi chip,
mass storage device, USB keyboard connected directly and using
high-speed hub.

Suspend/resume is not 100% complete though. I can use USB serial
port adapter if it's suspended/resumed unconnected. But it stuck if I do
the test while connected. Is it the right way to test it?

Which suspend you mean system/resume suspend or USB suspend/resume?

You should implement a musb_set_hw_power_sleep() too. This handles system going into suspend. You should probably reset that adapter at this point.

static void
musb_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
        struct ehci_softc *sc = EHCI_BUS2SC(bus);

        switch (state) {
        case USB_HW_POWER_SUSPEND:
        case USB_HW_POWER_RESUME:

If the musb requires that you stop tokens before going in and out of suspend, you need to add functions like this:


On the related note: can somebody suggest budget USB protocol analyzer
with support for high-speed bus?


There are more, but I don't have the list right now.

You can probably just remove this check. We don't support LOW speed in device mode.

-               if ((udev->speed != USB_SPEED_FULL) &&
-                   (udev->speed != USB_SPEED_HIGH)) {
-                       /* not supported */
-                       return;
+               if (sc->sc_mode != MUSB2_HOST_MODE) {
+                       if ((udev->speed != USB_SPEED_FULL) &&
+                           (udev->speed != USB_SPEED_HIGH)) {
+                               /* not supported */
+                               return;
+                       }

The musbotg_channel_free function is not sufficient! You need to program a non-existing device address like 127 and wait for 2 ms I recommend. The ABORT bits don't work with this controller last time I tried them! You can verify this by loading and unloading the wireless driver. I guess that IN tokens don't stop when you unload the driver. You will see this using an USB analyzer.

+#define        MUSB2_MAX_DEVICES (USB_MAX_DEVICES - 1)

+static void    
+musbotg_channel_free(struct musbotg_softc *sc, struct musbotg_td *td)
+       DPRINTFN(1, "ep_no=%d\n", td->channel);
+       if (sc->sc_mode == MUSB2_DEVICE_MODE)
+               return;
+       if (td == NULL)
+               return;
+       if (td->channel == -1)
+               return;
+       musbotg_ep_int_set(sc, td->channel, 0);
+       sc->sc_channel_mask &= ~(1 << td->channel);
+       td->channel = -1;

/* force transfer failure */
XXX channel should not be re-used until after 2*125us. Can probably use ticks for this!


The 2ms can be done asynchronosly by implementing this function. See EHCI driver.

static void
musbotg_get_dma_delay(struct usb_device *udev, uint32_t *pus)

        if (host_mode)
                *pus = 2000;                   /* microseconds */
                *pus = 0;

freebsd-usb@freebsd.org mailing list
To unsubscribe, send any mail to "freebsd-usb-unsubscr...@freebsd.org"

Reply via email to