[PATCH v7 usb-next 3/4] usb: core: hcd: integrate the PHY roothub wrapper

Chunfeng Yun chunfeng.yun at mediatek.com
Mon Oct 23 17:07:36 PDT 2017


On Mon, 2017-10-23 at 23:57 +0200, Martin Blumenstingl wrote:
> This integrates the PHY roothub wrapper into the core hcd
> infrastructure. Multiple PHYs which are part of the roothub devicetree
> node (which is a sub-node of the sysdev's node) are now managed
> (= powered on/off when needed), by the new usb_phy_roothub code.
> 
> One example where this is required is the Amlogic GXL and GXM SoCs:
> They are using a dwc3 USB controller with up to three ports enabled on
> the internal roothub. Using only the top-level "phy" properties does not
> work here since one can only specify one "usb2-phy" and one "usb3-phy",
> while actually at least two "usb2-phy" have to be specified.
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>
> Tested-by: Neil Armstrong <narmstrong at baylibre.com>
> Acked-by: Alan Stern <stern at rowland.harvard.edu>
> ---
>  drivers/usb/core/hcd.c  | 26 ++++++++++++++++++++++++++
>  include/linux/usb/hcd.h |  1 +
>  2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
> index 67aa3d039b9b..6ee97222cdad 100644
> --- a/drivers/usb/core/hcd.c
> +++ b/drivers/usb/core/hcd.c
> @@ -50,6 +50,7 @@
>  #include <linux/usb/otg.h>
>  
>  #include "usb.h"
> +#include "phy.h"
>  
> 
>  /*-------------------------------------------------------------------------*/
> @@ -2271,6 +2272,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
>  		usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
>  		hcd->state = HC_STATE_SUSPENDED;
>  
> +		usb_phy_roothub_power_off(hcd->phy_roothub);
> +
>  		/* Did we race with a root-hub wakeup event? */
>  		if (rhdev->do_remote_wakeup) {
>  			char	buffer[6];
> @@ -2307,6 +2310,11 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
>  		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
>  		return 0;
>  	}
> +
> +	status = usb_phy_roothub_power_on(hcd->phy_roothub);
> +	if (status)
> +		return status;
> +
>  	if (!hcd->driver->bus_resume)
>  		return -ENOENT;
>  	if (HCD_RH_RUNNING(hcd))
> @@ -2344,6 +2352,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
>  		}
>  	} else {
>  		hcd->state = old_state;
> +		usb_phy_roothub_power_off(hcd->phy_roothub);
>  		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
>  				"resume", status);
>  		if (status != -ESHUTDOWN)
> @@ -2780,6 +2789,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
>  		}
>  	}
>  
> +	hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev);
> +	if (IS_ERR(hcd->phy_roothub)) {
> +		retval = PTR_ERR(hcd->phy_roothub);
> +		goto err_phy_roothub_init;
> +	}
> +
> +	retval = usb_phy_roothub_power_on(hcd->phy_roothub);
> +	if (retval)
> +		goto err_usb_phy_roothub_power_on;
> +
>  	dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
>  
>  	/* Keep old behaviour if authorized_default is not in [0, 1]. */
> @@ -2944,6 +2963,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
>  err_register_bus:
>  	hcd_buffer_destroy(hcd);
>  err_create_buf:
> +	usb_phy_roothub_power_off(hcd->phy_roothub);
> +err_usb_phy_roothub_power_on:
> +	usb_phy_roothub_exit(hcd->phy_roothub);
> +err_phy_roothub_init:
>  	if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
>  		phy_power_off(hcd->phy);
>  		phy_exit(hcd->phy);
> @@ -3028,6 +3051,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
>  	usb_deregister_bus(&hcd->self);
>  	hcd_buffer_destroy(hcd);
>  
> +	usb_phy_roothub_power_off(hcd->phy_roothub);
> +	usb_phy_roothub_exit(hcd->phy_roothub);
> +
>  	if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
>  		phy_power_off(hcd->phy);
>  		phy_exit(hcd->phy);
> diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
> index a1f03ebfde47..6915b2afc209 100644
> --- a/include/linux/usb/hcd.h
> +++ b/include/linux/usb/hcd.h
> @@ -103,6 +103,7 @@ struct usb_hcd {
>  	 */
>  	struct usb_phy		*usb_phy;
>  	struct phy		*phy;
> +	struct usb_phy_roothub	*phy_roothub;
>  
>  	/* Flags that need to be manipulated atomically because they can
>  	 * change while the host controller is running.  Always use

Tested-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
Acked-by: Chunfeng Yun <chunfeng.yun at mediatek.com>






More information about the linux-amlogic mailing list