summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Czechowski <lukasz.czechowski@thaumatec.com>2025-07-22 11:55:36 +0200
committerTom Rini <trini@konsulko.com>2025-07-30 07:57:17 -0600
commit3eb6b0f504f7b6ed3d7786c48fc15fa4d8708d7c (patch)
tree10da7d40ab631adf3523e4738e02d48739004e5d
parent42a025412d737cd57874b81de8c8f49fea538c8b (diff)
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 <quentin.schulz@cherry.de> Signed-off-by: Lukasz Czechowski <lukasz.czechowski@thaumatec.com>
-rw-r--r--common/usb_onboard_hub.c68
1 files changed, 51 insertions, 17 deletions
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[] = {