usb: add a flag to skip PHY initialization to struct usb_hcd
authorMartin Blumenstingl <martin.blumenstingl@googlemail.com>
Sat, 3 Mar 2018 21:43:03 +0000 (22:43 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 Mar 2018 17:43:52 +0000 (09:43 -0800)
The USB HCD core driver parses the device-tree node for "phys" and
"usb-phys" properties. It also manages the power state of these PHYs
automatically.
However, drivers may opt-out of this behavior by setting "phy" or
"usb_phy" in struct usb_hcd to a non-null value. An example where this
is required is the "Qualcomm USB2 controller", implemented by the
chipidea driver. The hardware requires that the PHY is only powered on
after the "reset completed" event from the controller is received.

A follow-up patch will allow the USB HCD core driver to manage more than
one PHY. Add a new "skip_phy_initialization" bitflag to struct usb_hcd
so drivers can opt-out of any PHY management provided by the USB HCD
core driver.

This also updates the existing drivers so they use the new flag if they
want to opt out of the PHY management provided by the USB HCD core
driver. This means that for these drivers the new "multiple PHY"
handling (which will be added in a follow-up patch) will be disabled as
well.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Acked-by: Peter Chen <peter.chen@nxp.com>
Tested-by: Neil Armstrong <narmstrong@baylibre.con>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/chipidea/host.c
drivers/usb/core/hcd.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-platform.c
drivers/usb/host/xhci-plat.c
include/linux/usb/hcd.h

index 19d60ed7e41f277e084b3fc2dba7ae7f278dfcbe..af45aa3222b5ce1c99ccb4de586c988d3b3a0b9f 100644 (file)
@@ -124,10 +124,8 @@ static int host_start(struct ci_hdrc *ci)
 
        hcd->power_budget = ci->platdata->power_budget;
        hcd->tpl_support = ci->platdata->tpl_support;
-       if (ci->phy)
-               hcd->phy = ci->phy;
-       else
-               hcd->usb_phy = ci->usb_phy;
+       if (ci->phy || ci->usb_phy)
+               hcd->skip_phy_initialization = 1;
 
        ehci = hcd_to_ehci(hcd);
        ehci->caps = ci->hw_bank.cap;
index fc32391a34d5db0c4951d2f1a50c4be8ccb97f94..f2307470a31e17538505e046a3a58719a5269478 100644 (file)
@@ -2727,7 +2727,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
        int retval;
        struct usb_device *rhdev;
 
-       if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) {
+       if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->skip_phy_initialization) {
                struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 0);
 
                if (IS_ERR(phy)) {
@@ -2745,7 +2745,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
                }
        }
 
-       if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) {
+       if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->skip_phy_initialization) {
                struct phy *phy = phy_get(hcd->self.sysdev, "usb");
 
                if (IS_ERR(phy)) {
index c5094cb88cd5d61a1c00544a16c343aa304d02d1..0a9fd2022acfa46d4ecb535b0e7303ef60375c6a 100644 (file)
@@ -155,6 +155,8 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
                        retval = -ENODEV;
                        goto err2;
                }
+
+               hcd->skip_phy_initialization = 1;
        }
 #endif
        return retval;
index b065a960adc2ddb69002550b2a229d114f678316..b91eea8c73ae6cfdcbe8829bad7cc281b14d3a46 100644 (file)
@@ -219,9 +219,9 @@ static int ehci_platform_probe(struct platform_device *dev)
                        if (IS_ERR(priv->phys[phy_num])) {
                                err = PTR_ERR(priv->phys[phy_num]);
                                        goto err_put_hcd;
-                       } else if (!hcd->phy) {
+                       } else {
                                /* Avoiding phy_get() in usb_add_hcd() */
-                               hcd->phy = priv->phys[phy_num];
+                               hcd->skip_phy_initialization = 1;
                        }
                }
 
index c809f7d2f08f61173abbc7799309858a4f05a074..a6f4389f7e88da420295a751880150861b343697 100644 (file)
@@ -461,6 +461,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                goto cleanup_clk_en;
        }
        hcd->usb_phy = u_phy;
+       hcd->skip_phy_initialization = 1;
 
        tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
                "nvidia,needs-double-reset");
index 0201c49bc4fc95672c8f49c4b4c624657cce2eb0..d8d35d45645627f40abc2a0bc2b714562178c88c 100644 (file)
@@ -230,6 +230,7 @@ static int ohci_omap_reset(struct usb_hcd *hcd)
                } else {
                        return -EPROBE_DEFER;
                }
+               hcd->skip_phy_initialization = 1;
                ohci->start_hnp = start_hnp;
        }
 #endif
index 1e6c954f4b3f4157ccbfefb0c302783957a78045..62ef36a9333fac43f510328d9e6d120e33dead04 100644 (file)
@@ -186,9 +186,9 @@ static int ohci_platform_probe(struct platform_device *dev)
                        if (IS_ERR(priv->phys[phy_num])) {
                                err = PTR_ERR(priv->phys[phy_num]);
                                goto err_put_hcd;
-                       } else if (!hcd->phy) {
+                       } else {
                                /* Avoiding phy_get() in usb_add_hcd() */
-                               hcd->phy = priv->phys[phy_num];
+                               hcd->skip_phy_initialization = 1;
                        }
                }
 
index 6f038306c14d6c244dc9a7305adce185ee3aaecc..6700e5ee82ad667051ced538cbf4e0c0dd964470 100644 (file)
@@ -284,6 +284,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
                ret = usb_phy_init(hcd->usb_phy);
                if (ret)
                        goto put_usb3_hcd;
+               hcd->skip_phy_initialization = 1;
        }
 
        ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
index 17690052882244922c27f253901e4cd0228c2dc4..693502c84c04f6b886aebcc9be0cc35a717ccbf8 100644 (file)
@@ -151,6 +151,12 @@ struct usb_hcd {
        unsigned                msix_enabled:1; /* driver has MSI-X enabled? */
        unsigned                msi_enabled:1;  /* driver has MSI enabled? */
        unsigned                remove_phy:1;   /* auto-remove USB phy */
+       /*
+        * do not manage the PHY state in the HCD core, instead let the driver
+        * handle this (for example if the PHY can only be turned on after a
+        * specific event)
+        */
+       unsigned                skip_phy_initialization:1;
 
        /* The next flag is a stopgap, to be removed when all the HCDs
         * support the new root-hub polling mechanism. */