summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorFabrice Gasnier <fabrice.gasnier@foss.st.com>2022-12-12 13:44:35 +0300
committerPatrice Chotard <patrice.chotard@foss.st.com>2023-01-12 18:19:53 +0300
commitba1fa2abde88257c29ee4d8f3884ab6657a3193a (patch)
treefedeefef60560b17e84e797192723a757e4577bd /common
parent79da4074ddf0f76b3c2ec26d58c9a33ac7884222 (diff)
downloadu-boot-ba1fa2abde88257c29ee4d8f3884ab6657a3193a.tar.xz
usb: onboard-hub: add driver to manage onboard hub supplies
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@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@5800d000 usb_hub 0 [ + ] usb_onboard_hub | | `-- hub@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@foss.st.com> Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Diffstat (limited to 'common')
-rw-r--r--common/Makefile1
-rw-r--r--common/usb_onboard_hub.c62
2 files changed, 63 insertions, 0 deletions
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 <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),
+};