[Patch v2 09/10] usb: chipidea: host: add ehci quirk for imx controller

Alan Stern stern at rowland.harvard.edu
Wed Oct 23 10:46:09 EDT 2013


On Tue, 22 Oct 2013, Peter Chen wrote:

> When the port goes to suspend or finishes resme, it needs to
> notify PHY, it is not a standard EHCI operation, so we add a
> quirk for it.

Actually, this _should_ be a standard EHCI operation.  But we have to
figure out a way to do it that will work on all platforms.

Felipe, any ideas?

Alan Stern

> 
> Signed-off-by: Peter Chen <peter.chen at freescale.com>
> ---
>  drivers/usb/chipidea/host.c  |  129 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/usb/chipidea.h |    1 +
>  2 files changed, 130 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> index 283b385..c1d05c4 100644
> --- a/drivers/usb/chipidea/host.c
> +++ b/drivers/usb/chipidea/host.c
> @@ -34,6 +34,10 @@
>  
>  static struct hc_driver __read_mostly ci_ehci_hc_driver;
>  static int (*orig_bus_suspend)(struct usb_hcd *hcd);
> +static int (*orig_bus_resume)(struct usb_hcd *hcd);
> +static int (*orig_hub_control)(struct usb_hcd *hcd,
> +				u16 typeReq, u16 wValue, u16 wIndex,
> +				char *buf, u16 wLength);
>  
>  static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
>  {
> @@ -75,12 +79,131 @@ static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
>  				 */
>  				udelay(125);
>  			}
> +			if (hcd->phy && test_bit(port, &ehci->bus_suspended)
> +				&& (ehci_port_speed(ehci, portsc) ==
> +					USB_PORT_STAT_HIGH_SPEED))
> +				/*
> +				 * notify the USB PHY, it is for global
> +				 * suspend case.
> +				 */
> +				usb_phy_notify_suspend(hcd->phy,
> +					USB_SPEED_HIGH);
>  		}
>  	}
>  
>  	return 0;
>  }
>  
> +static int ci_imx_ehci_bus_resume(struct usb_hcd *hcd)
> +{
> +	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> +	int port;
> +
> +	int ret = orig_bus_resume(hcd);
> +
> +	if (ret)
> +		return ret;
> +
> +	port = HCS_N_PORTS(ehci->hcs_params);
> +	while (port--) {
> +		u32 __iomem *reg = &ehci->regs->port_status[port];
> +		u32 portsc = ehci_readl(ehci, reg);
> +		/*
> +		 * Notify PHY after resume signal has finished, it is
> +		 * for global suspend case.
> +		 */
> +		if (hcd->phy
> +			&& test_bit(port, &ehci->bus_suspended)
> +			&& (portsc & PORT_CONNECT)
> +			&& (ehci_port_speed(ehci, portsc) ==
> +				USB_PORT_STAT_HIGH_SPEED))
> +			/* notify the USB PHY */
> +			usb_phy_notify_resume(hcd->phy, USB_SPEED_HIGH);
> +	}
> +
> +	return 0;
> +}




More information about the linux-arm-kernel mailing list