[PATCH 0/3] usb: ehci-generic: setup a bulk of phy when possible

one USB controller can have multiple ports specified in dts, all of them should be setup to make use of all possible ports.
Signed-off-by: Yang Xiwen forbidden405@outlook.com --- Yang Xiwen (3): phy: add generic_setup(shutdown)_phy_bulk() test: phy: test generic_setup(shutdown)_phy_bulk() usb: ehci: Make usage of generic_{setup,shutdown}_phy_bulk() helpers
drivers/phy/phy-uclass.c | 33 +++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-generic.c | 8 ++++---- include/generic-phy.h | 29 +++++++++++++++++++++++++++++ test/dm/phy.c | 4 ++++ 4 files changed, 70 insertions(+), 4 deletions(-) --- base-commit: b6d8969bcb94321dfed1399f2eaa8768ba42caaa change-id: 20240201-ehci-6c3aa7d97932
Best regards,

From: Yang Xiwen forbidden405@outlook.com
They are the bulk version of generic_setup(shutdown)_phy().
Signed-off-by: Yang Xiwen forbidden405@outlook.com --- drivers/phy/phy-uclass.c | 33 +++++++++++++++++++++++++++++++++ include/generic-phy.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index 0dcfe258bc..d50ebbe3a0 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -528,6 +528,28 @@ int generic_setup_phy(struct udevice *dev, struct phy *phy, int index) return ret; }
+int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk *bulk) +{ + struct phy *phys = bulk->phys; + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = generic_setup_phy(dev, &phys[i], i); + if (ret) { + pr_err("Can't setup PHY%d\n", i); + goto phys_setup_err; + } + } + + return 0; + +phys_setup_err: + for (; i > 0; i--) + generic_shutdown_phy(&phys[i - 1]); + + return ret; +} + int generic_shutdown_phy(struct phy *phy) { int ret; @@ -542,6 +564,17 @@ int generic_shutdown_phy(struct phy *phy) return generic_phy_exit(phy); }
+int generic_shutdown_phy_bulk(struct phy_bulk *bulk) +{ + struct phy *phys = bulk->phys; + int i, ret = 0; + + for (i = 0; i < bulk->count; i++) + ret |= generic_shutdown_phy(&phys[i]); + + return ret; +} + UCLASS_DRIVER(phy) = { .id = UCLASS_PHY, .name = "phy", diff --git a/include/generic-phy.h b/include/generic-phy.h index eaab749166..2d1bf7c1ea 100644 --- a/include/generic-phy.h +++ b/include/generic-phy.h @@ -420,6 +420,16 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk); */ int generic_setup_phy(struct udevice *dev, struct phy *phy, int index);
+/** + * generic_setup_phy() - Get, initialize and power on all phys in a phy bulk. + * + * @dev: The consumer device. + * @bulk: A pointer to the PHY bulk + * + * Return: 0 if OK, or negative error code. + */ +int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk *bulk); + /** * generic_shutdown_phy() - Power off and de-initialize phy. * @@ -429,6 +439,15 @@ int generic_setup_phy(struct udevice *dev, struct phy *phy, int index); */ int generic_shutdown_phy(struct phy *phy);
+/** + * generic_shutdown_phy_bulk() - Power off and de-initialize all phys in a phy bulk. + * + * @bulk: A pointer to the PHY bulk. + * + * Return: 0 if OK, or negative error code. + */ +int generic_shutdown_phy_bulk(struct phy_bulk *bulk); + #else /* CONFIG_PHY */
static inline int generic_phy_init(struct phy *phy) @@ -514,11 +533,21 @@ static inline int generic_setup_phy(struct udevice *dev, struct phy *phy, int in return 0; }
+static inline int generic_setup_phy_bulk(struct udevice *dev, struct phy_bulk *bulk) +{ + return 0; +} + static inline int generic_shutdown_phy(struct phy *phy) { return 0; }
+static inline int generic_shutdown_phy_bulk(struct phy_bulk *bulk) +{ + return 0; +} + #endif /* CONFIG_PHY */
/**

From: Yang Xiwen forbidden405@outlook.com
add unittests for the newly introduced helper functions.
Signed-off-by: Yang Xiwen forbidden405@outlook.com --- test/dm/phy.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/test/dm/phy.c b/test/dm/phy.c index 0cf3689fde..cb16844a0a 100644 --- a/test/dm/phy.c +++ b/test/dm/phy.c @@ -159,6 +159,8 @@ static int dm_test_phy_bulk(struct unit_test_state *uts) ut_asserteq(0, generic_phy_power_on_bulk(&phys)); ut_asserteq(0, generic_phy_power_off_bulk(&phys)); ut_asserteq(0, generic_phy_exit_bulk(&phys)); + ut_asserteq(0, generic_setup_phy_bulk(parent, &phys)); + ut_asserteq(0, generic_shutdown_phy_bulk(&phys));
/* has a known problem phy */ ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS, @@ -171,6 +173,8 @@ static int dm_test_phy_bulk(struct unit_test_state *uts) ut_asserteq(-EIO, generic_phy_power_on_bulk(&phys)); ut_asserteq(-EIO, generic_phy_power_off_bulk(&phys)); ut_asserteq(0, generic_phy_exit_bulk(&phys)); + ut_asserteq(-EIO, generic_setup_phy_bulk(parent, &phys)); + ut_asserteq(-EIO, generic_shutdown_phy_bulk(&phys));
return 0; }

From: Yang Xiwen forbidden405@outlook.com
Replace generic_setup_phy() and generic_shutdown_phy() by respectively generic_setup_phy_bulk() and generic_shutdown_phy_bulk().
Signed-off-by: Yang Xiwen forbidden405@outlook.com --- drivers/usb/host/ehci-generic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 936e30438d..e109d84d73 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -25,7 +25,7 @@ struct generic_ehci { struct ehci_ctrl ctrl; struct clk_bulk clocks; struct reset_ctl_bulk resets; - struct phy phy; + struct phy_bulk phys; struct udevice *vbus_supply; };
@@ -95,7 +95,7 @@ static int ehci_usb_probe(struct udevice *dev) if (err) goto reset_err;
- err = generic_setup_phy(dev, &priv->phy, 0); + err = generic_setup_phy_bulk(dev, &priv->phys); if (err) goto regulator_err;
@@ -110,7 +110,7 @@ static int ehci_usb_probe(struct udevice *dev) return 0;
phy_err: - ret = generic_shutdown_phy(&priv->phy); + ret = generic_shutdown_phy_bulk(&priv->phys); if (ret) dev_err(dev, "failed to shutdown usb phy (ret=%d)\n", ret);
@@ -140,7 +140,7 @@ static int ehci_usb_remove(struct udevice *dev) if (ret) return ret;
- ret = generic_shutdown_phy(&priv->phy); + ret = generic_shutdown_phy_bulk(&priv->phys); if (ret) return ret;

On 2/1/2024 10:07 PM, Marek Vasut wrote:
On 2/1/24 14:16, Yang Xiwen via B4 Relay wrote:
one USB controller can have multiple ports specified in dts, all of them should be setup to make use of all possible ports.
Is there an example of such a system ?
I'm going to send one, but not now because of some stuck patches. Running `grep 'phys = <.*>, <.*>' arch/arm/dts/*.dtsi` in the dts directory gives us some existing examples, though not very much.
participants (3)
-
Marek Vasut
-
Yang Xiwen
-
Yang Xiwen via B4 Relay