[PATCH v2 4/5] usb: onboard-hub: Add support for multiple power supplies

Lukasz Czechowski lukasz.czechowski at thaumatec.com
Mon May 26 16:24:23 CEST 2025


Some of the onboard hubs require multiple power supplies, so extend
the driver to support them.
The implementation is inspired by the kernel driver, as introduced
by commit [1] in the v6.10 kernel.

[1] https://github.com/torvalds/linux/commit/ec1848cd5df426f57a7f6a8a6b95b69259c52cfc
Signed-off-by: Lukasz Czechowski <lukasz.czechowski at thaumatec.com>
---
 common/usb_onboard_hub.c | 65 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 49 insertions(+), 16 deletions(-)

diff --git a/common/usb_onboard_hub.c b/common/usb_onboard_hub.c
index dcaa24d30ece..2d2114ea6d17 100644
--- a/common/usb_onboard_hub.c
+++ b/common/usb_onboard_hub.c
@@ -20,14 +20,18 @@
 #define USB5744_CONFIG_REG_ACCESS	0x0037
 #define USB5744_CONFIG_REG_ACCESS_LSB	0x99
 
+#define MAX_SUPPLIES 2
+
 struct onboard_hub {
-	struct udevice *vdd;
+	struct udevice *vdd[MAX_SUPPLIES];
 	struct gpio_desc *reset_gpio;
 };
 
 struct onboard_hub_data {
 	unsigned long reset_us;
 	unsigned long power_on_delay_us;
+	unsigned int num_supplies;
+	const char * const supply_names[MAX_SUPPLIES];
 	int (*init)(struct udevice *dev);
 };
 
@@ -139,30 +143,53 @@ int usb_onboard_hub_reset(struct udevice *dev)
 	return 0;
 }
 
+static int usb_onboard_hub_power_off(struct udevice *dev)
+{
+	struct onboard_hub_data *data =
+		(struct onboard_hub_data *)dev_get_driver_data(dev);
+	struct onboard_hub *hub = dev_get_priv(dev);
+	int ret = 0;
+	int i;
+
+	for (i = data->num_supplies - 1; i >= 0; i--)
+		if (hub->vdd[i])
+			ret |= regulator_set_enable_if_allowed(hub->vdd[i], false);
+
+	return ret;
+}
+
 static int usb_onboard_hub_probe(struct udevice *dev)
 {
 	struct onboard_hub_data *data =
 		(struct onboard_hub_data *)dev_get_driver_data(dev);
 	struct onboard_hub *hub = dev_get_priv(dev);
+	unsigned int i;
 	int ret;
 
-	ret = device_get_supply_regulator(dev, "vdd-supply", &hub->vdd);
-	if (ret && ret != -ENOENT) {
-		dev_err(dev, "can't get vdd-supply: %d\n", ret);
-		return ret;
+	if (data->num_supplies > MAX_SUPPLIES) {
+		dev_err(dev, "invalid supplies number, max supported: %d\n", MAX_SUPPLIES);
+		return -EINVAL;
 	}
 
-	if (hub->vdd) {
-		ret = regulator_set_enable_if_allowed(hub->vdd, true);
-		if (ret && ret != -ENOSYS) {
-			dev_err(dev, "can't enable vdd-supply: %d\n", ret);
-			return ret;
+	for (i = 0; i < data->num_supplies; i++) {
+		ret = device_get_supply_regulator(dev, data->supply_names[i], &hub->vdd[i]);
+		if (ret && ret != -ENOENT) {
+			dev_err(dev, "can't get %s: %d\n", data->supply_names[i], ret);
+			goto err_supply;
+		}
+
+		if (hub->vdd[i]) {
+			ret = regulator_set_enable_if_allowed(hub->vdd[i], true);
+			if (ret && ret != -ENOSYS) {
+				dev_err(dev, "can't enable %s: %d\n", data->supply_names[i], ret);
+				goto err_supply;
+			}
 		}
 	}
 
 	ret = usb_onboard_hub_reset(dev);
 	if (ret)
-		return ret;
+		goto err_supply;
 
 	if (data->init) {
 		ret = data->init(dev);
@@ -174,6 +201,8 @@ static int usb_onboard_hub_probe(struct udevice *dev)
 	return 0;
 err:
 	dm_gpio_set_value(hub->reset_gpio, 0);
+err_supply:
+	usb_onboard_hub_power_off(dev);
 	return ret;
 }
 
@@ -209,7 +238,7 @@ static int usb_onboard_hub_bind(struct udevice *dev)
 static int usb_onboard_hub_remove(struct udevice *dev)
 {
 	struct onboard_hub *hub = dev_get_priv(dev);
-	int ret;
+	int ret = 0, ret2;
 
 	if (hub->reset_gpio) {
 		ret = dm_gpio_set_value(hub->reset_gpio, 1);
@@ -218,22 +247,26 @@ static int usb_onboard_hub_remove(struct udevice *dev)
 				ret);
 	}
 
-	ret = regulator_set_enable_if_allowed(hub->vdd, false);
-	if (ret)
-		dev_err(dev, "can't disable vdd-supply: %d\n", ret);
+	ret2 = usb_onboard_hub_power_off(dev);
+	if (ret2)
+		dev_err(dev, "can't disable regulators: %d\n", ret2);
 
-	return ret;
+	return ret | ret2;
 }
 
 static const struct onboard_hub_data usb2514_data = {
 	.power_on_delay_us = 500,
 	.reset_us = 1,
+	.num_supplies = 1,
+	.supply_names = { "vdd-supply" },
 };
 
 static const struct onboard_hub_data usb5744_data = {
 	.init = usb5744_i2c_init,
 	.power_on_delay_us = 1000,
 	.reset_us = 5,
+	.num_supplies = 1,
+	.supply_names = { "vdd-supply" },
 };
 
 static const struct udevice_id usb_onboard_hub_ids[] = {

-- 
2.43.0



More information about the U-Boot mailing list