mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
usb: add a flag to skip PHY initialization to struct usb_hcd
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>
This commit is contained in:
parent
05db0dcc70
commit
4e88d4c083
9 changed files with 19 additions and 10 deletions
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in a new issue