Re: [PATCH] usb: xhci-plat: Add generic PHY support

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

 



++ Felipe Balbi

Thanks & Regards,
Srinath Mannam.

On Thu, Jul 14, 2016 at 2:03 PM, Srinath Mannam
<srinath.mannam@xxxxxxxxxxxx> wrote:
> Generic phy support added in xhci platform driver.
> In the case of multiple phys to the xhci controller, this approach
> is helpful to pass multiple phandles to xhci platform driver from
> xhci device node.
>
> Signed-off-by: Srinath Mannam <srinath.mannam@xxxxxxxxxxxx>
> Reviewed-by: Ray Jui <ray.jui@xxxxxxxxxxxx>
> Reviewed-by: Scott Branden <scott.branden@xxxxxxxxxxxx>
>
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index 676ea45..c734e2e 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -15,6 +15,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> +#include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
>  #include <linux/usb/phy.h>
>  #include <linux/slab.h>
> @@ -84,6 +85,52 @@ static int xhci_plat_start(struct usb_hcd *hcd)
>         return xhci_run(hcd);
>  }
>
> +static int xhci_platform_phy_on(struct usb_hcd *hcd)
> +{
> +       struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
> +       int ret, phy_num;
> +
> +       if (hcd->usb_phy) {
> +               ret = usb_phy_init(hcd->usb_phy);
> +               if (ret)
> +                       return ret;
> +       }
> +       for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
> +               ret = phy_init(priv->phys[phy_num]);
> +               if (ret)
> +                       goto err_exit_phy;
> +               ret = phy_power_on(priv->phys[phy_num]);
> +               if (ret) {
> +                       phy_exit(priv->phys[phy_num]);
> +                       goto err_exit_phy;
> +               }
> +       }
> +
> +       return 0;
> +
> +err_exit_phy:
> +       while (--phy_num >= 0) {
> +               phy_power_off(priv->phys[phy_num]);
> +               phy_exit(priv->phys[phy_num]);
> +       }
> +
> +       return ret;
> +}
> +
> +static void xhci_platform_phy_off(struct usb_hcd *hcd)
> +{
> +       struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
> +       int phy_num;
> +
> +       if (hcd->usb_phy)
> +               usb_phy_shutdown(hcd->usb_phy);
> +
> +       for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
> +               phy_power_off(priv->phys[phy_num]);
> +               phy_exit(priv->phys[phy_num]);
> +       }
> +}
> +
>  #ifdef CONFIG_OF
>  static const struct xhci_plat_priv xhci_plat_marvell_armada = {
>         .init_quirk = xhci_mvebu_mbus_init_quirk,
> @@ -146,8 +193,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
>         struct resource         *res;
>         struct usb_hcd          *hcd;
>         struct clk              *clk;
> +       struct xhci_plat_priv   *priv;
>         int                     ret;
> -       int                     irq;
> +       int                     irq, phy_num;
>
>         if (usb_disabled())
>                 return -ENODEV;
> @@ -199,10 +247,10 @@ static int xhci_plat_probe(struct platform_device *pdev)
>         }
>
>         xhci = hcd_to_xhci(hcd);
> +       priv = hcd_to_xhci_priv(hcd);
>         match = of_match_node(usb_xhci_of_match, node);
>         if (match) {
>                 const struct xhci_plat_priv *priv_match = match->data;
> -               struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
>
>                 /* Just copy data for now */
>                 if (priv_match)
> @@ -233,12 +281,32 @@ static int xhci_plat_probe(struct platform_device *pdev)
>                 if (ret == -EPROBE_DEFER)
>                         goto put_usb3_hcd;
>                 hcd->usb_phy = NULL;
> -       } else {
> -               ret = usb_phy_init(hcd->usb_phy);
> -               if (ret)
> +       }
> +
> +       priv->num_phys = of_count_phandle_with_args(pdev->dev.of_node,
> +                       "phys", "#phy-cells");
> +
> +       if (priv->num_phys > 0) {
> +               priv->phys = devm_kcalloc(&pdev->dev, priv->num_phys,
> +                               sizeof(struct phy *), GFP_KERNEL);
> +               if (!priv->phys)
> +                       return -ENOMEM;
> +       } else
> +               priv->num_phys = 0;
> +
> +       for (phy_num = 0; phy_num < priv->num_phys; phy_num++) {
> +               priv->phys[phy_num] = devm_of_phy_get_by_index(
> +                               &pdev->dev, pdev->dev.of_node, phy_num);
> +               if (IS_ERR(priv->phys[phy_num])) {
> +                       ret = PTR_ERR(priv->phys[phy_num]);
>                         goto put_usb3_hcd;
> +               }
>         }
>
> +       ret = xhci_platform_phy_on(hcd);
> +       if (ret < 0)
> +               goto put_usb3_hcd;
> +
>         ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
>         if (ret)
>                 goto disable_usb_phy;
> @@ -254,7 +322,7 @@ dealloc_usb2_hcd:
>         usb_remove_hcd(hcd);
>
>  disable_usb_phy:
> -       usb_phy_shutdown(hcd->usb_phy);
> +       xhci_platform_phy_off(hcd);
>
>  put_usb3_hcd:
>         usb_put_hcd(xhci->shared_hcd);
> @@ -276,7 +344,7 @@ static int xhci_plat_remove(struct platform_device *dev)
>         struct clk *clk = xhci->clk;
>
>         usb_remove_hcd(xhci->shared_hcd);
> -       usb_phy_shutdown(hcd->usb_phy);
> +       xhci_platform_phy_off(hcd);
>
>         usb_remove_hcd(hcd);
>         usb_put_hcd(xhci->shared_hcd);
> diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
> index 9af0cb4..1fe9c21 100644
> --- a/drivers/usb/host/xhci-plat.h
> +++ b/drivers/usb/host/xhci-plat.h
> @@ -15,6 +15,8 @@
>
>  struct xhci_plat_priv {
>         const char *firmware_name;
> +       struct phy **phys;
> +       int num_phys;
>         void (*plat_start)(struct usb_hcd *);
>         int (*init_quirk)(struct usb_hcd *);
>  };
> --
> 2.9.0
>
--
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