greatscottgadgets/luna

SoC: usb_device_connect=0 does not disconnect device

gregdavill opened this issue · 2 comments

I'm using Luna as a HS USB wishbone peripheral in a SoC bootloader design for the ButterStick. I'd like to be able to disconnect the USB interface from firmware to support re-enumeration.

USBDevice.connect is a signal that is connected via the standard SoC interface, Which has the following description:

class USBDevice(Elaboratable):

    Attributes
    ----------

    connect: Signal(), input
        Held high to keep the current USB device connected; or held low to disconnect.

If I hold connect low on power-up the device never appears, as expected. When I pull this signal high the device appears, as expected. However If the device is attached then pulling this signal low I'd expect the host to detect we've disconnected. But that is not the case.

The gateware seems to remove the termination if connect drops low.

self.utmi.term_select.eq(reset_sequencer.termination_select & self.connect),

But this results in termination being set to 0. Which is defined as HS_NORMAL

class UTMITerminationSelect:
    """ Enumeration that specifies meanings of the UTMI TermSelect bit. """

    HS_NORMAL    = 0
    HS_CHIRP     = 1
    LS_FS_NORMAL = 1

A quick fix I've found is to mask vbus_connected with self.connect. So that when we bring 'self.connect' LOW it's equivalent in logic to a vbus removal. With this in place the device correctly disconnects.

This works, but I'm not sure if this is the correct place to perform this mask.

diff --git a/luna/gateware/usb/usb2/device.py b/luna/gateware/usb/usb2/device.py
index 67e4c6b..4956cd3 100644
--- a/luna/gateware/usb/usb2/device.py
+++ b/luna/gateware/usb/usb2/device.py
@@ -232,7 +232,7 @@ class USBDevice(Elaboratable):
         m.d.comb += [
             reset_sequencer.bus_busy        .eq(self.bus_busy),
 
-            reset_sequencer.vbus_connected  .eq(~self.utmi.session_end),
+            reset_sequencer.vbus_connected  .eq(~self.utmi.session_end & self.connect),
             reset_sequencer.line_state      .eq(self.utmi.line_state),
         ]
 

Thank you for this information! I've upgraded this issue to bug status. I will leave this issue open until it is addressed.

Fixed in #212.