From: Lukasz Czechowski Date: Tue, 22 Jul 2025 09:55:36 +0000 (+0200) Subject: usb: onboard-hub: Add support for multiple power supplies X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3eb6b0f504f7b6ed3d7786c48fc15fa4d8708d7c;p=thirdparty%2Fu-boot.git usb: onboard-hub: Add support for multiple power supplies 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 Reviewed-by: Quentin Schulz Signed-off-by: Lukasz Czechowski --- diff --git a/common/usb_onboard_hub.c b/common/usb_onboard_hub.c index 046831d0966..dbe4c3cf9b8 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,59 @@ 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, ret2; + unsigned int i; + + for (i = data->num_supplies; i > 0; i--) { + if (hub->vdd[i-1]) { + ret2 = regulator_set_enable_if_allowed(hub->vdd[i-1], false); + if (ret2 && ret2 != -ENOSYS) { + dev_err(dev, "can't disable %s: %d\n", data->supply_names[i-1], ret2); + ret |= ret2; + } + } + } + + 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 && ret != -ENOSYS) { - 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 && ret != -ENOSYS) { + 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 +207,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; } @@ -218,24 +253,23 @@ static int usb_onboard_hub_remove(struct udevice *dev) ret); } - if (hub->vdd) { - ret = regulator_set_enable_if_allowed(hub->vdd, false); - if (ret) - dev_err(dev, "can't disable vdd-supply: %d\n", ret); - } - + ret |= usb_onboard_hub_power_off(dev); return ret; } 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[] = {