From 0ce433043353cf76691ad71fbecd45d2002030c1 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 25 Apr 2015 07:48:20 -0600 Subject: [PATCH] USB OHCI: Need to preserve the speed bit when reconfiguring ep0 --- arch/arm/src/lpc17xx/lpc17_usbhost.c | 26 ++++++++------------------ arch/arm/src/sama5/sam_ohci.c | 22 +++++++++------------- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c index bcfbad225b..4f082f313a 100644 --- a/arch/arm/src/lpc17xx/lpc17_usbhost.c +++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c @@ -1979,6 +1979,7 @@ static int lpc17_ep0configure(struct usbhost_driver_s *drvr, { struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr; struct lpc17_ed_s *ed; + uint32_t hwctrl; DEBUGASSERT(drvr != NULL && ep0 != NULL && funcaddr < 128 && maxpacketsize < 2048); ed = (struct lpc17_ed_s *)ep0; @@ -1987,19 +1988,14 @@ static int lpc17_ep0configure(struct usbhost_driver_s *drvr, lpc17_takesem(&priv->exclsem); - /* Set the EP0 ED control word */ + /* Set the EP0 ED control word (preserving only speed) */ - ed->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | + hwctrl = ed->hw.ctrl & ED_CONTROL_S; + hwctrl |= (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | + (uint32_t)ED_CONTROL_D_TD1 | (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT; + ed->hw.ctrl = hwctrl; - if (priv->rhport.hport.speed == USB_SPEED_LOW) - { - ed->hw.ctrl |= ED_CONTROL_S; - } - - /* Set the transfer type to control */ - - ed->xfrtype = USB_EP_ATTR_XFER_CONTROL; lpc17_givesem(&priv->exclsem); uvdbg("EP0 CTRL:%08x\n", ed->hw.ctrl); @@ -2085,7 +2081,7 @@ static int lpc17_epalloc(struct usbhost_driver_s *drvr, /* Check for a low-speed device */ - if (priv->rhport.hport.speed == USB_SPEED_LOW) + if (hport->speed == USB_SPEED_LOW) { ed->hw.ctrl |= ED_CONTROL_S; } @@ -3228,13 +3224,6 @@ static void lpc17_disconnect(struct usbhost_driver_s *drvr) static inline void lpc17_ep0init(struct lpc17_usbhost_s *priv) { - /* Set up some default values */ - - (void)lpc17_ep0configure(&priv->drvr, (usbhost_ep_t)EDCTRL, 1, 8); - - /* Initialize the common tail TD.*/ - - memset(TDTAIL, 0, sizeof(struct lpc17_gtd_s)); /* Initialize the common tail TD. */ memset(TDTAIL, 0, sizeof(struct lpc17_gtd_s)); @@ -3245,6 +3234,7 @@ static inline void lpc17_ep0init(struct lpc17_usbhost_s *priv) memset(EDCTRL, 0, sizeof(struct lpc17_ed_s)); EDCTRL->hw.headp = (uint32_t)TDTAIL; EDCTRL->hw.tailp = (uint32_t)TDTAIL; + EDCTRL->xfrtype = USB_EP_ATTR_XFER_CONTROL; /* Set the head of the control list to the NULL (for now). */ diff --git a/arch/arm/src/sama5/sam_ohci.c b/arch/arm/src/sama5/sam_ohci.c index cf8d0a8673..1538f2bf23 100644 --- a/arch/arm/src/sama5/sam_ohci.c +++ b/arch/arm/src/sama5/sam_ohci.c @@ -1479,6 +1479,7 @@ static int sam_ep0enqueue(struct sam_rhport_s *rhport) (void)sam_ep0configure(&rhport->drvr, &rhport->ep0, 0, 8); edctrl->hw.ctrl |= ED_CONTROL_K; edctrl->eplist = &rhport->ep0; + edctrl->xfrtype = USB_EP_ATTR_XFER_CONTROL; /* Link the common tail TD to the ED's TD list */ @@ -2361,6 +2362,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; struct sam_eplist_s *ep0list = (struct sam_eplist_s *)ep0; struct sam_ed_s *edctrl; + uint32_t hwctrl; DEBUGASSERT(rhport && maxpacketsize < 2048); @@ -2370,19 +2372,13 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, sam_takesem(&g_ohci.exclsem); - /* Set the EP0 ED control word */ + /* Set the EP0 ED control word (preserving only speed) */ - edctrl->hw.ctrl = (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | - (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT; - - if (rhport->hport.hport.speed == USB_SPEED_LOW) - { - edctrl->hw.ctrl |= ED_CONTROL_S; - } - - /* Set the transfer type to control */ - - edctrl->xfrtype = USB_EP_ATTR_XFER_CONTROL; + hwctrl = ed->hw.ctrl & ED_CONTROL_S; + hwctrl |= (uint32_t)funcaddr << ED_CONTROL_FA_SHIFT | + (uint32_t)ED_CONTROL_D_TD1 | + (uint32_t)maxpacketsize << ED_CONTROL_MPS_SHIFT; + ed->hw.ctrl = hwctrl; /* Flush the modified control ED to RAM */ @@ -2504,7 +2500,7 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr, /* Check for a low-speed device */ - if (rhport->hport.hport.speed == USB_SPEED_LOW) + if (hport->speed == USB_SPEED_LOW) { ed->hw.ctrl |= ED_CONTROL_S; }