Re: Need PHY reset after USB device disconnected

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Mathias,

Please provide your suggestions to resolve this.

Thank you.

Regards,
Srinath.

On Thu, Aug 3, 2017 at 11:42 PM, Srinath Mannam
<srinath.mannam@xxxxxxxxxxxx> wrote:
> Hi Mathias,
>
> In our SOC, xHCI controller has three ports. In that one is SS and two
> HS ports, all ports are connected with separate phy controller.
>
> We have a bug in HS phy controllers.
> Because of this bug, HS phy controller needs to reset after
> disconnected the device in the corresponding HS port.
>
> I could not find any available mechanism or quirks in kernel to handle
> these cases.
> So, I did modifications in xhci-plat.c, xhci.c and xhci-hub.c files to
> fix this issue.
>
> But the modifications are not cleaner to upstream.
>
> Please help me in the implementation of proper fix.
>
> Below are the code changes.
>
> ---
>  drivers/usb/host/xhci-hub.c  |  9 +++++++++
>  drivers/usb/host/xhci-plat.c | 11 +++++++++++
>  drivers/usb/host/xhci.c      |  2 ++
>  drivers/usb/host/xhci.h      |  1 +
>  4 files changed, 23 insertions(+)
>
> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> index 0ef1690..3fdb07d 100644
> --- a/drivers/usb/host/xhci-hub.c
> +++ b/drivers/usb/host/xhci-hub.c
> @@ -1193,6 +1193,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16
> typeReq, u16 wValue,
>                 case USB_PORT_FEAT_C_PORT_CONFIG_ERROR:
>                         xhci_clear_port_change_bit(xhci, wValue, wIndex,
>                                         port_array[wIndex], temp);
> +                       if ((wValue == USB_PORT_FEAT_C_CONNECTION) &&
> +                                       !(temp & PORT_CONNECT) &&
> +                                       (hcd->speed < HCD_USB3)) {
> +
> +                               hcd->driver->port_power(hcd,
> +                                                       wIndex +
> +                                                       xhci->num_usb3_ports,
> +                                                       false);
> +                       }
>                         break;
>                 case USB_PORT_FEAT_ENABLE:
>                         xhci_disable_port(hcd, xhci, wIndex,
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index 1a1d6b8..2e1facd 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -30,11 +30,13 @@ static struct hc_driver __read_mostly xhci_plat_hc_driver;
>
>  static int xhci_plat_setup(struct usb_hcd *hcd);
>  static int xhci_plat_start(struct usb_hcd *hcd);
> +static int xhci_plat_portpower(struct usb_hcd *hcd, int portnum, bool enable);
>
>  static const struct xhci_driver_overrides xhci_plat_overrides __initconst = {
>         .extra_priv_size = sizeof(struct xhci_plat_priv),
>         .reset = xhci_plat_setup,
>         .start = xhci_plat_start,
> +       .port_power = xhci_plat_portpower,
>  };
>
>  static void xhci_priv_plat_start(struct usb_hcd *hcd)
> @@ -64,6 +66,15 @@ static void xhci_plat_quirks(struct device *dev,
> struct xhci_hcd *xhci)
>          */
>         xhci->quirks |= XHCI_PLAT;
>  }
> +static int xhci_plat_portpower(struct usb_hcd *hcd, int portnum, bool enable)
> +{
> +       struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
> +
> +       if (enable == false)
> +               phy_reset(priv->phys[portnum]);
> +
> +       return 0;
> +}
>
>  /* called during probe() after chip reset completes */
>  static int xhci_plat_setup(struct usb_hcd *hcd)
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 1a4ca02..a41c009 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -5028,6 +5028,8 @@ void xhci_init_driver(struct hc_driver *drv,
>                         drv->reset = over->reset;
>                 if (over->start)
>                         drv->start = over->start;
> +               if (over->port_power)
> +                       drv->port_power = over->port_power;
>         }
>  }
>  EXPORT_SYMBOL_GPL(xhci_init_driver);
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index f945380..08c573c 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -1692,6 +1692,7 @@ struct xhci_driver_overrides {
>         size_t extra_priv_size;
>         int (*reset)(struct usb_hcd *hcd);
>         int (*start)(struct usb_hcd *hcd);
> +       int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable);
>  };
>
>  #define        XHCI_CFC_DELAY          10
> --
> 2.7.4
>
>
> Regards,
> Srinath.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux