usb: ehci: pass full speed devices to companion controller
Subsystems (2)
PATCH 1/1 usb: ehci: pass full speed devices to companion controller
According to the "Enhanced Host Controller Interface Specification for Universal Serial Bus" after a USB port reset the EHCI Driver checks the PortEnable bit in the PORTSC register. If set to a one, the connected device is a high-speed device [...]. At the time the EHCI Driver receives the port reset and enable request the LineStatus bits might indicate a low-speed device. Additionally, when the port reset process is complete, the PortEnable field may indicate that a full-speed device is attached. In either case the EHCI driver sets the PortOwner bit in the PORTSC register to a one to release port ownership to a companion host controller.
--- drivers/usb/host/ehci-hcd.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
drivers/usb/host/ehci-hcd.c +21 -6
@@ -477,6 +477,18 @@ static inline void ehci_powerup_fixup(struct ehci_priv *ehci) }#endif +static void pass_to_companion (struct ehci_priv *ehci,int port) +{ +uint32_t *status_reg = (uint32_t *)&ehci->hcor->or_portsc[port -1 ]; +uint32_t reg =ehci_readl (status_reg); + + reg &= ~EHCI_PS_CLEAR ; +dev_dbg (ehci->dev,"port %d --> companion\n" , + port -1 ); + reg |=EHCI_PS_PO ; +ehci_writel (status_reg, reg); +} +static int ehci_submit_root (struct usb_device *dev,unsigned long pipe,void *buffer,int length,struct devrequest *req)
@@ -509,6 +521,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,return -1 ; } status_reg = (uint32_t *)&ehci->hcor->or_portsc[port -1 ]; +if (ehci_readl (status_reg) &EHCI_PS_PO ) { +dev_dbg (ehci->dev,"Port %d is owned by companion controller\n" , port); +return -1 ; + }break ;default : status_reg =NULL ;
@@ -655,11 +671,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,if ((reg & (EHCI_PS_PE |EHCI_PS_CS )) ==EHCI_PS_CS && !ehci_is_TDI () &&EHCI_PS_IS_LOWSPEED (reg)) { -/* Low speed device, give up ownership. */ -dev_dbg (ehci->dev,"port %d low speed --> companion\n" , - port -1 ); - reg |=EHCI_PS_PO ; -ehci_writel (status_reg, reg); +pass_to_companion (ehci, port);break ; }else {int ret;
@@ -690,7 +702,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,else dev_err (ehci->dev,"port(%d) reset error\n" , port -1 ); - +mdelay (200 ); + reg =ehci_readl (status_reg); +if (!(reg &EHCI_PS_PE )) +pass_to_companion (ehci, port); }break ;default :
Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
Sascha Hauer
AppliedQuoted 10 lines · Peter Mamonov
According to the "Enhanced Host Controller Interface Specification for Universal Serial Bus" after a USB port reset the EHCI Driver checks the PortEnable bit in the PORTSC register. If set to a one, the connected device is a high-speed device [...]. At the time the EHCI Driver receives the port reset and enable request the LineStatus bits might indicate a low-speed device. Additionally, when the port reset process is complete, the PortEnable field may indicate that a full-speed device is attached. In either case the EHCI driver sets the PortOwner bit in the PORTSC register to a one to release port ownership to a companion host controller.
Quoted 4 lines
Signed-off-by Peter Mamonov <[email protected]>--- drivers/usb/host/ehci-hcd.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
Applied, thanks
Sascha
Quoted 69 lines
drivers/usb/host/ehci-hcd.c +21
-6@@ -477,6 +477,18 @@ static inline void ehci_powerup_fixup(struct ehci_priv *ehci) }#endif +static void pass_to_companion (struct ehci_priv *ehci,int port) +{ +uint32_t *status_reg = (uint32_t *)&ehci->hcor->or_portsc[port -1 ]; +uint32_t reg =ehci_readl (status_reg); + + reg &= ~EHCI_PS_CLEAR ; +dev_dbg (ehci->dev,"port %d --> companion\n" , + port -1 ); + reg |=EHCI_PS_PO ; +ehci_writel (status_reg, reg); +} +static int ehci_submit_root (struct usb_device *dev,unsigned long pipe,void *buffer,int length,struct devrequest *req)@@ -509,6 +521,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,return -1 ; } status_reg = (uint32_t *)&ehci->hcor->or_portsc[port -1 ]; +if (ehci_readl (status_reg) &EHCI_PS_PO ) { +dev_dbg (ehci->dev,"Port %d is owned by companion controller\n" , port); +return -1 ; + }break ;default : status_reg =NULL ;@@ -655,11 +671,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,if ((reg & (EHCI_PS_PE |EHCI_PS_CS )) ==EHCI_PS_CS && !ehci_is_TDI () &&EHCI_PS_IS_LOWSPEED (reg)) { -/* Low speed device, give up ownership. */ -dev_dbg (ehci->dev,"port %d low speed --> companion\n" , - port -1 ); - reg |=EHCI_PS_PO ; -ehci_writel (status_reg, reg); +pass_to_companion (ehci, port);break ; }else {int ret;@@ -690,7 +702,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,else dev_err (ehci->dev,"port(%d) reset error\n" , port -1 ); - +mdelay (200 ); + reg =ehci_readl (status_reg); +if (!(reg &EHCI_PS_PE )) +pass_to_companion (ehci, port); }break ;default :Signature · 7 lines
2.11.0 _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox
Signature · 9 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list [email protected] http://lists.infradead.org/mailman/listinfo/barebox