[PATCH 1/3] usb: onboard-hub: add driver to manage onboard hub supplies

Patrice CHOTARD patrice.chotard at foss.st.com
Tue Jan 3 17:33:59 CET 2023


Hi Fabrice

On 12/12/22 11:44, Fabrice Gasnier wrote:
> The main issue the driver addresses is that a USB hub needs to be
> powered before it can be discovered. This is often solved by using
> "regulator-always-on".
> 
> This driver is inspired by the Linux v6.1 driver. It only enables (or
> disables) the hub vdd (3v3) supply, so it can be enumerated.
> Scanning of the device tree is done in a similar manner to the sandbox,
> by the usb-uclass. DT part looks like:
> 
> &usbh_ehci {
> 	...
> 	#address-cells = <1>;
> 	#size-cells = <0>;
> 	hub at 1 {
> 		compatible = "usb424,2514";
> 		reg = <1>;
> 		vdd-supply = <&v3v3>;
> 	};
> };
> 
> When the bus gets probed, the driver is automatically probed/removed from
> the bus tree, as an example on stm32:
> STM32MP> usb start
> starting USB...
> STM32MP> dm tree
>  Class     Index  Probed  Driver                Name
> -----------------------------------------------------------
>  usb           0  [ + ]   ehci_generic          |   |-- usb at 5800d000
>  usb_hub       0  [ + ]   usb_onboard_hub       |   |   `-- hub at 1
>  usb_hub       1  [ + ]   usb_hub               |   |       `-- usb_hub
> 
> STM32MP> usb tree
> USB device tree:
>   1  Hub (480 Mb/s, 0mA)
>   |  u-boot EHCI Host Controller
>   |
>   +-2  Hub (480 Mb/s, 2mA)
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at foss.st.com>
> ---
> 
>  common/Makefile               |  1 +
>  common/usb_onboard_hub.c      | 62 +++++++++++++++++++++++++++++++++++
>  drivers/usb/Kconfig           | 10 ++++++
>  drivers/usb/host/usb-uclass.c | 16 +++++----
>  4 files changed, 83 insertions(+), 6 deletions(-)
>  create mode 100644 common/usb_onboard_hub.c
> 
> diff --git a/common/Makefile b/common/Makefile
> index 20addfb244c2..7789aab484fd 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -26,6 +26,7 @@ obj-$(CONFIG_PHYLIB) += miiphyutil.o
>  obj-$(CONFIG_USB_HOST) += usb.o usb_hub.o
>  obj-$(CONFIG_USB_GADGET) += usb.o usb_hub.o
>  obj-$(CONFIG_USB_STORAGE) += usb_storage.o
> +obj-$(CONFIG_USB_ONBOARD_HUB) += usb_onboard_hub.o
>  
>  # others
>  obj-$(CONFIG_CONSOLE_MUX) += iomux.o
> diff --git a/common/usb_onboard_hub.c b/common/usb_onboard_hub.c
> new file mode 100644
> index 000000000000..89e18a2ddad6
> --- /dev/null
> +++ b/common/usb_onboard_hub.c
> @@ -0,0 +1,62 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Driver for onboard USB hubs
> + *
> + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
> + *
> + * Mostly inspired by Linux kernel v6.1 onboard_usb_hub driver
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <power/regulator.h>
> +
> +struct onboard_hub {
> +	struct udevice *vdd;
> +};
> +
> +static int usb_onboard_hub_probe(struct udevice *dev)
> +{
> +	struct onboard_hub *hub = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = device_get_supply_regulator(dev, "vdd-supply", &hub->vdd);
> +	if (ret) {
> +		dev_err(dev, "can't get vdd-supply: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = regulator_set_enable_if_allowed(hub->vdd, true);
> +	if (ret)
> +		dev_err(dev, "can't enable vdd-supply: %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static int usb_onboard_hub_remove(struct udevice *dev)
> +{
> +	struct onboard_hub *hub = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = regulator_set_enable_if_allowed(hub->vdd, false);
> +	if (ret)
> +		dev_err(dev, "can't disable vdd-supply: %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static const struct udevice_id usb_onboard_hub_ids[] = {
> +	/* Use generic usbVID,PID dt-bindings (usb-device.yaml) */
> +	{ .compatible = "usb424,2514" }, /* USB2514B USB 2.0 */
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(usb_onboard_hub) = {
> +	.name	= "usb_onboard_hub",
> +	.id	= UCLASS_USB_HUB,
> +	.probe = usb_onboard_hub_probe,
> +	.remove = usb_onboard_hub_remove,
> +	.of_match = usb_onboard_hub_ids,
> +	.priv_auto = sizeof(struct onboard_hub),
> +};
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index 3afb45d5ccb2..d10ee6853d40 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -106,6 +106,16 @@ config USB_KEYBOARD
>  	  Say Y here if you want to use a USB keyboard for U-Boot command line
>  	  input.
>  
> +config USB_ONBOARD_HUB
> +	bool "Onboard USB hub support"
> +	depends on DM_USB
> +	---help---
> +	  Say Y here if you want to support discrete onboard USB hubs that
> +	  don't require an additional control bus for initialization, but
> +	  need some non-trivial form of initialization, such as enabling a
> +	  power regulator. An example for such a hub is the Microchip
> +	  USB2514B.
> +
>  if USB_KEYBOARD
>  
>  config USB_KEYBOARD_FN_KEYS
> diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
> index 060f3441df0c..f5dc93ffee39 100644
> --- a/drivers/usb/host/usb-uclass.c
> +++ b/drivers/usb/host/usb-uclass.c
> @@ -271,19 +271,23 @@ int usb_init(void)
>  		/* init low_level USB */
>  		printf("Bus %s: ", bus->name);
>  
> -#ifdef CONFIG_SANDBOX
>  		/*
>  		 * For Sandbox, we need scan the device tree each time when we
>  		 * start the USB stack, in order to re-create the emulated USB
>  		 * devices and bind drivers for them before we actually do the
>  		 * driver probe.
> +		 *
> +		 * For USB onboard HUB, we need to do some non-trivial init
> +		 * like enabling a power regulator, before enumeration.
>  		 */
> -		ret = dm_scan_fdt_dev(bus);
> -		if (ret) {
> -			printf("Sandbox USB device scan failed (%d)\n", ret);
> -			continue;
> +		if (IS_ENABLED(CONFIG_SANDBOX) ||
> +		    IS_ENABLED(CONFIG_USB_ONBOARD_HUB)) {
> +			ret = dm_scan_fdt_dev(bus);
> +			if (ret) {
> +				printf("USB device scan from fdt failed (%d)", ret);
> +				continue;
> +			}
>  		}
> -#endif
>  
>  		ret = device_probe(bus);
>  		if (ret == -ENODEV) {	/* No such device. */

Reviewed-by: Patrice Chotard <patrice.chotard at foss.st.com>

Thanks
Patrice


More information about the U-Boot mailing list