Date: Tue, 5 Jan 2016 09:27:32 +0100 From: Hans Petter Selasky <hps@selasky.org> To: Sebastian Huber <sebastian.huber@embedded-brains.de>, freebsd-usb@freebsd.org Subject: Re: dwc_otg: Problem with directly connected full/low speed devices Message-ID: <568B7E74.5080600@selasky.org> In-Reply-To: <568B69FE.5030307@embedded-brains.de> References: <568B69FE.5030307@embedded-brains.de>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
On 01/05/16 08:00, Sebastian Huber wrote:
> Hello,
>
> I use an Altera Cyclone V development kit which the dwc_otg driver from
> FreeBSD. The device enumeration of full/low speed devices directly
> connected to the root hub fails since split transactions are used. If I
> connect them via a hub it works fine. I used the following hack to get
> them working with a direct connection:
>
> diff --git a/sys/dev/usb/controller/dwc_otg.c
> b/sys/dev/usb/controller/dwc_otg.c
> index 2110b94..37cca8e 100644
> --- a/sys/dev/usb/controller/dwc_otg.c
> +++ b/sys/dev/usb/controller/dwc_otg.c
> @@ -3340,7 +3340,7 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
> case USB_SPEED_FULL:
> case USB_SPEED_LOW:
> /* check if root HUB port is running High Speed */
> - if (xfer->xroot->udev->parent_hs_hub != NULL) {
> + if (xfer->xroot->udev->parent_hs_hub != NULL &&
> 0) {
> hcsplt = HCSPLT_SPLTENA |
> (xfer->xroot->udev->hs_port_no <<
> HCSPLT_PRTADDR_SHIFT) |
>
> I am not sure how to fix this properly. Is this a specific problem with
> the Altera Cyclone V board or is this problem also present on other
> boards e.g. RPI2?
>
Hi,
Does the attached patch solve your problem?
--HPS
[-- Attachment #2 --]
Index: dwc_otg.c
===================================================================
--- dwc_otg.c (revision 293158)
+++ dwc_otg.c (working copy)
@@ -456,6 +456,18 @@
return (0);
}
+static uint8_t
+dwc_otg_uses_split(struct usb_device *udev)
+{
+ /*
+ * When a LOW or FULL speed device is connected directly to
+ * the USB port we don't use split transactions:
+ */
+ return (udev->speed != USB_SPEED_HIGH &&
+ udev->parent_hs_hub != NULL &&
+ udev->parent_hs_hub->parent_hub != NULL);
+}
+
static void
dwc_otg_update_host_frame_interval(struct dwc_otg_softc *sc)
{
@@ -3329,16 +3341,16 @@
else
hcchar |= (td->ep_type << HCCHAR_EPTYPE_SHIFT);
- if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_LOW)
- hcchar |= HCCHAR_LSPDDEV;
if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN)
hcchar |= HCCHAR_EPDIR_IN;
switch (xfer->xroot->udev->speed) {
+ case USB_SPEED_LOW:
+ hcchar |= HCCHAR_LSPDDEV;
+ /* FALLTHROUGH */
case USB_SPEED_FULL:
- case USB_SPEED_LOW:
/* check if root HUB port is running High Speed */
- if (xfer->xroot->udev->parent_hs_hub != NULL) {
+ if (dwc_otg_uses_split(xfer->xroot->udev)) {
hcsplt = HCSPLT_SPLTENA |
(xfer->xroot->udev->hs_port_no <<
HCSPLT_PRTADDR_SHIFT) |
@@ -4160,7 +4172,10 @@
framenum = DSTS_SOFFN_GET(temp);
}
- if (xfer->xroot->udev->parent_hs_hub != NULL)
+ /*
+ * Check if port is doing 8000 or 1000 frames per second:
+ */
+ if (sc->sc_flags.status_high_speed)
framenum /= 8;
framenum &= DWC_OTG_FRAME_MASK;
@@ -4837,7 +4852,7 @@
td = USB_ADD_BYTES(parm->buf, parm->size[0]);
/* compute shared bandwidth resource index for TT */
- if (parm->udev->parent_hs_hub != NULL && parm->udev->speed != USB_SPEED_HIGH) {
+ if (dwc_otg_uses_split(parm->udev)) {
if (parm->udev->parent_hs_hub->ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT)
td->tt_index = parm->udev->device_index;
else
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?568B7E74.5080600>
