diff --git a/common/Makefile b/common/Makefile index 20addfb244..7789aab484 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 0000000000..89e18a2dda --- /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 +#include +#include +#include + +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 8efd461457..ebe6bf9498 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -105,6 +105,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 956e2a4e8e..93c318c3d1 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. */