[PATCH v6 0/2] arm: dts: rockchip: rk3399: usb: ehci: Fix EHCI probe in rk3399 to access peripherals by USB 2.

EHCI probing in Rock pi 4 currently fails.
Add a clock driver for usb2phy so that probing EHCI does not fail when missing one of the clocks in the bundle for usb_host0_ehci, since usb2phy is UCLASS_PHY but not UCLASS_CLK.
Xavier Drudis Ferran (2): arm: dts: rockchip: rk3399: usb: ehci: Fix EHCI probe in rk3399 to access peripherals by USB 2. arm: rk3399: usb2phy: phy-rockchip-inno-usb2.c: Implement operations for the 480MHz usb2phy clock in rk3399.
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 97 ++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-)
Cc: Simon Glass sjg@chromium.org Cc: Philipp Tomsich philipp.tomsich@vrull.eu Cc: Kever Yang kever.yang@rock-chips.com Cc: Lukasz Majewski lukma@denx.de Cc: Sean Anderson seanga2@gmail.com Cc: Marek Vasut marex@denx.de Cc: Christoph Fritz chf.fritz@googlemail.com Cc: Jagan Teki jagan@amarulasolutions.com Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat
---
Changes:
v6: just retested over current next branch and some corrections to message and headers (no changes to code).
v5: fixes a bug that Christoph Fritz discovered, consisting in the wrong eror code returned when enabling or disabling the clock because property_enable() returns an error code in linux but the modified register value in U-Boot. This caused the clk disable to abort before freeing the clock.
v4: move v3 to one patch in the series and add a second patch to add operations to enable disable the usb2phy 480Mhz clock. Also, honour clock-output-names for what is worth.
v3: implement option 5 (bind usb2phy as a clk driver too) instead of option 1 (ehci-generic.c tolerates missing clocks).
v2: implement option 1 (ehci-generic.c tolerates missing clocks) instead of option 3 (change dts node to remove the missing clock).

arch/arm/dts/rk3399.dtsi has a node
usb_host0_ehci: usb@fe380000 { compatible = "generic-ehci";
with clocks:
clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>, <&u2phy0>;
The first 2 refer to nodes with class UCLASS_CLK, but &u2phy0 has class UCLASS_PHY.
u2phy0: usb2phy@e450 { compatible = "rockchip,rk3399-usb2phy";
Since clk_get_bulk() only looks for devices with UCLASS_CLK, it fails with -ENODEV and then ehci_usb_probe() aborts.
The consequence is peripherals connected to a USB 2 port (e.g. in a Rock Pi 4 the white port, nearer the edge) not being detected. They're detected if CONFIG_USB_OHCI_GENERIC is selected in Kconfig, because ohci_usb_probe() does not abort when one clk_get_by_index() fails, but then they work in USB 1 mode.
rk3399.dtsi comes from linux and the u2phy0 was added[1] to the clock list in:
commit b5d1c57299734f5b54035ef2e61706b83041f20c Author: William wu wulf@rock-chips.com Date: Wed Dec 21 18:41:05 2016 +0800
arm64: dts: rockchip: add u2phy clock for ehci and ohci of rk3399
We found that the suspend process was blocked when it run into ehci/ohci module due to clk-480m of usb2-phy was disabled. [...]
Suspend concerns don't apply to U-Boot, and the problem with U-Boot failing to probe EHCI doesn't apply to linux, because in linux rockchip_usb2phy_clk480m_register makes u2phy0 a proper clock provider when called by rockchip_usb2phy_probe().
So I can think of a few alternative solutions:
1- Change ehci_usb_probe() to make it more similar to ohci_usb_probe(), and survive failure to get one clock. Looks a little harder, and I don't know whether it could break something if it ignored a clock that was important for something else than suspend.
2- Change rk3399.dtsi effectively reverting the linux commit b5d1c57299734f5b54035ef2e61706b83041f20c. This dealigns the .dtsi from linux and seems fragile at the next synchronisation.
3- Change the clock list in rk3399-u-boot.dtsi or somewhere else. This survives .dts* sync but may survive "too much" and miss some change from linux that we might want.
4- Enable CONFIG_USB_OHCI_GENERIC and use the ports in USB 1 mode. This would need to be made for all boards using rk3399. In a simple test reading one file from USB storage it gave 769.5 KiB/s instead of 20.5 MiB/s with solution 2.
5- Trying to replicate linux and have usb2phy somehow provide a clk, or have a separate clock device for usb2phy in addition to the phy device.
This patch tries to implement option 5 as Marek Vasut requested in December 5th. Options 1 and 3 didn't get through [2][3].
It just registers usb2phy as a clock driver (device_bind_driver() didn't work but device_bind_driver_to_node() did), without any specific operations, so that ehci-generic.c finds it and is happy. It worked in my tests on a Rock Pi 4 B+ (rk3399).
Link: [1] https://lkml.kernel.org/lkml/1731551.Q6cHK6n5ZM@phil/T/ [2] https://patchwork.ozlabs.org/project/uboot/patch/20220701185959.GC1700@begut... [3] https://patchwork.ozlabs.org/project/uboot/patch/Y44+ayJfUlI08ptM@localhost/ Cc: Simon Glass sjg@chromium.org Cc: Philipp Tomsich philipp.tomsich@vrull.eu Cc: Kever Yang kever.yang@rock-chips.com Cc: Lukasz Majewski lukma@denx.de Cc: Sean Anderson seanga2@gmail.com Cc: Marek Vasut marex@denx.de Cc: Christoph Fritz chf.fritz@googlemail.com Cc: Jagan Teki jagan@amarulasolutions.com
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 55e1dbcfef..2f31350134 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -7,7 +7,7 @@ */
#include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <asm/global_data.h> #include <dm/device_compat.h> @@ -168,6 +168,9 @@ static struct phy_ops rockchip_usb2phy_ops = { .of_xlate = rockchip_usb2phy_of_xlate, };
+static struct clk_ops rockchip_usb2phy_clk_ops = { +}; + static int rockchip_usb2phy_probe(struct udevice *dev) { struct rockchip_usb2phy *priv = dev_get_priv(dev); @@ -249,6 +252,18 @@ static int rockchip_usb2phy_bind(struct udevice *dev) } }
+ if (!ret) { + node = dev_ofnode(dev); + name = ofnode_get_name(node); + dev_dbg(dev, "clk for node %s\n", name); + ret = device_bind_driver_to_node(dev, "rockchip_usb2phy_clock", + name, node, &usb2phy_dev); + if (ret) { + dev_err(dev, + "'%s' cannot bind 'rockchip_usb2phy_clock'\n", name); + } + } + return ret; }
@@ -366,6 +381,12 @@ U_BOOT_DRIVER(rockchip_usb2phy_port) = { .ops = &rockchip_usb2phy_ops, };
+U_BOOT_DRIVER(rockchip_usb2phy_clock) = { + .name = "rockchip_usb2phy_clock", + .id = UCLASS_CLK, + .ops = &rockchip_usb2phy_clk_ops, +}; + U_BOOT_DRIVER(rockchip_usb2phy) = { .name = "rockchip_usb2phy", .id = UCLASS_PHY,

On 6/4/23 10:13, Xavier Drudis Ferran wrote:
arch/arm/dts/rk3399.dtsi has a node
usb_host0_ehci: usb@fe380000 { compatible = "generic-ehci";
with clocks:
clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>, <&u2phy0>;
The first 2 refer to nodes with class UCLASS_CLK, but &u2phy0 has class UCLASS_PHY.
u2phy0: usb2phy@e450 { compatible = "rockchip,rk3399-usb2phy";
Since clk_get_bulk() only looks for devices with UCLASS_CLK, it fails with -ENODEV and then ehci_usb_probe() aborts.
The consequence is peripherals connected to a USB 2 port (e.g. in a Rock Pi 4 the white port, nearer the edge) not being detected. They're detected if CONFIG_USB_OHCI_GENERIC is selected in Kconfig, because ohci_usb_probe() does not abort when one clk_get_by_index() fails, but then they work in USB 1 mode.
rk3399.dtsi comes from linux and the u2phy0 was added[1] to the clock list in:
commit b5d1c57299734f5b54035ef2e61706b83041f20c Author: William wu <wulf@rock-chips.com> Date: Wed Dec 21 18:41:05 2016 +0800 arm64: dts: rockchip: add u2phy clock for ehci and ohci of rk3399 We found that the suspend process was blocked when it run into ehci/ohci module due to clk-480m of usb2-phy was disabled. [...]
Suspend concerns don't apply to U-Boot, and the problem with U-Boot failing to probe EHCI doesn't apply to linux, because in linux rockchip_usb2phy_clk480m_register makes u2phy0 a proper clock provider when called by rockchip_usb2phy_probe().
So I can think of a few alternative solutions:
1- Change ehci_usb_probe() to make it more similar to ohci_usb_probe(), and survive failure to get one clock. Looks a little harder, and I don't know whether it could break something if it ignored a clock that was important for something else than suspend.
2- Change rk3399.dtsi effectively reverting the linux commit b5d1c57299734f5b54035ef2e61706b83041f20c. This dealigns the .dtsi from linux and seems fragile at the next synchronisation.
3- Change the clock list in rk3399-u-boot.dtsi or somewhere else. This survives .dts* sync but may survive "too much" and miss some change from linux that we might want.
4- Enable CONFIG_USB_OHCI_GENERIC and use the ports in USB 1 mode. This would need to be made for all boards using rk3399. In a simple test reading one file from USB storage it gave 769.5 KiB/s instead of 20.5 MiB/s with solution 2.
5- Trying to replicate linux and have usb2phy somehow provide a clk, or have a separate clock device for usb2phy in addition to the phy device.
This patch tries to implement option 5 as Marek Vasut requested in December 5th. Options 1 and 3 didn't get through [2][3].
It just registers usb2phy as a clock driver (device_bind_driver() didn't work but device_bind_driver_to_node() did), without any specific operations, so that ehci-generic.c finds it and is happy. It worked in my tests on a Rock Pi 4 B+ (rk3399).
Link: [1] https://lkml.kernel.org/lkml/1731551.Q6cHK6n5ZM@phil/T/ [2] https://patchwork.ozlabs.org/project/uboot/patch/20220701185959.GC1700@begut... [3] https://patchwork.ozlabs.org/project/uboot/patch/Y44+ayJfUlI08ptM@localhost/
Cc: Simon Glass sjg@chromium.org Cc: Philipp Tomsich philipp.tomsich@vrull.eu Cc: Kever Yang kever.yang@rock-chips.com Cc: Lukasz Majewski lukma@denx.de Cc: Sean Anderson seanga2@gmail.com Cc: Marek Vasut marex@denx.de Cc: Christoph Fritz chf.fritz@googlemail.com Cc: Jagan Teki jagan@amarulasolutions.com
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 55e1dbcfef..2f31350134 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -7,7 +7,7 @@ */
#include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <asm/global_data.h> #include <dm/device_compat.h> @@ -168,6 +168,9 @@ static struct phy_ops rockchip_usb2phy_ops = { .of_xlate = rockchip_usb2phy_of_xlate, };
+static struct clk_ops rockchip_usb2phy_clk_ops = { +};
- static int rockchip_usb2phy_probe(struct udevice *dev) { struct rockchip_usb2phy *priv = dev_get_priv(dev);
@@ -249,6 +252,18 @@ static int rockchip_usb2phy_bind(struct udevice *dev) } }
- if (!ret) {
Can $ret ever be != 0 here ?
btw. the dev_for_each_subnode() above is missing error handling, in case device_bind_driver_to_node() there returns non-zero, there should be some 'goto err' and 'err: dev_for_each_subnode() device_unbind()' fail path.
node = dev_ofnode(dev);
name = ofnode_get_name(node);
dev_dbg(dev, "clk for node %s\n", name);
ret = device_bind_driver_to_node(dev, "rockchip_usb2phy_clock",
name, node, &usb2phy_dev);
if (ret) {
dev_err(dev,
"'%s' cannot bind 'rockchip_usb2phy_clock'\n", name);
Use device_unbind() in fail path here too.
}
- }
- return ret; }
@@ -366,6 +381,12 @@ U_BOOT_DRIVER(rockchip_usb2phy_port) = { .ops = &rockchip_usb2phy_ops, };
+U_BOOT_DRIVER(rockchip_usb2phy_clock) = {
- .name = "rockchip_usb2phy_clock",
- .id = UCLASS_CLK,
- .ops = &rockchip_usb2phy_clk_ops,
+};
- U_BOOT_DRIVER(rockchip_usb2phy) = { .name = "rockchip_usb2phy", .id = UCLASS_PHY,

Thanks for your feedback.
El Sun, Jun 04, 2023 at 11:31:28AM +0200, Marek Vasut deia:
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 55e1dbcfef..2f31350134 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -7,7 +7,7 @@ */ #include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <asm/global_data.h> #include <dm/device_compat.h> @@ -168,6 +168,9 @@ static struct phy_ops rockchip_usb2phy_ops = { .of_xlate = rockchip_usb2phy_of_xlate, }; +static struct clk_ops rockchip_usb2phy_clk_ops = { +};
- static int rockchip_usb2phy_probe(struct udevice *dev) { struct rockchip_usb2phy *priv = dev_get_priv(dev);
@@ -249,6 +252,18 @@ static int rockchip_usb2phy_bind(struct udevice *dev) } }
- if (!ret) {
Can $ret ever be != 0 here ?
No, you're right. I can get rid of the if in v7.
btw. the dev_for_each_subnode() above is missing error handling, in case device_bind_driver_to_node() there returns non-zero, there should be some 'goto err' and 'err: dev_for_each_subnode() device_unbind()' fail path.
node = dev_ofnode(dev);
name = ofnode_get_name(node);
dev_dbg(dev, "clk for node %s\n", name);
ret = device_bind_driver_to_node(dev, "rockchip_usb2phy_clock",
name, node, &usb2phy_dev);
if (ret) {
dev_err(dev,
"'%s' cannot bind 'rockchip_usb2phy_clock'\n", name);
Use device_unbind() in fail path here too.
Well, dev_for_each_subnode wouldn't give me the dev to pass to device_unbind, but I can simply call device_chld_unbind(dev) on the error path (on the parent device) and that should clean up any bound children.
I'll fix it in v7, thanks.

This clock doesn't seem needed but appears in a phandle list used by ehci-generic.c to bulk enable it. The phandle list comes from linux, where it is needed for suspend/resume to work [1].
My tests give the same results with or without this patch, but Marek Vasut found it weird to declare an empty clk_ops [2].
So I adapted the code from linux 6.1-rc8 so that it hopefully works if it ever has some user. For now, without real use, it seems to at least not give any errors when called.
Link: [1] https://lkml.kernel.org/lkml/1731551.Q6cHK6n5ZM@phil/T/ [2] https://patchwork.ozlabs.org/project/uboot/patch/Y5IWpjYLB4aXMy9o@localhost/
Cc: Simon Glass sjg@chromium.org Cc: Philipp Tomsich philipp.tomsich@vrull.eu Cc: Kever Yang kever.yang@rock-chips.com Cc: Lukasz Majewski lukma@denx.de Cc: Sean Anderson seanga2@gmail.com Cc: Marek Vasut marex@denx.de Cc: Christoph Fritz chf.fritz@googlemail.com Cc: Jagan Teki jagan@amarulasolutions.com
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat ---
v6: just retested over current next branch and some corrections to message and headers (no changes to code).
v5: ignores the return value from property_enable() which is not an error code in U-Boot (unlike in linux). This avoid a false failure of rockchip_usb2phy_clk_disable() that interfered with clock disable and appeared to cause hang or reset.
--- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 2f31350134..451841b025 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -55,6 +55,7 @@ struct rockchip_usb2phy_port_cfg {
struct rockchip_usb2phy_cfg { unsigned int reg; + struct usb2phy_reg clkout_ctl; const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; };
@@ -76,6 +77,18 @@ static inline int property_enable(void *reg_base, return writel(val, reg_base + reg->offset); }
+static inline bool property_enabled(void *reg_base, + const struct usb2phy_reg *reg) +{ + unsigned int tmp, orig; + unsigned int mask = GENMASK(reg->bitend, reg->bitstart); + + orig = readl(reg_base + reg->offset); + + tmp = (orig & mask) >> reg->bitstart; + return tmp != reg->disable; +} + static const struct rockchip_usb2phy_port_cfg *us2phy_get_port(struct phy *phy) { @@ -168,7 +181,63 @@ static struct phy_ops rockchip_usb2phy_ops = { .of_xlate = rockchip_usb2phy_of_xlate, };
+/** + * round_rate() - Adjust a rate to the exact rate a clock can provide. + * @clk: The clock to manipulate. + * @rate: Desidered clock rate in Hz. + * + * Return: rounded rate in Hz, or -ve error code. + */ +ulong rockchip_usb2phy_clk_round_rate(struct clk *clk, ulong rate) +{ + return 480000000; +} + +/** + * enable() - Enable a clock. + * @clk: The clock to manipulate. + * + * Return: zero on success, or -ve error code. + */ +int rockchip_usb2phy_clk_enable(struct clk *clk) +{ + struct udevice *parent = dev_get_parent(clk->dev); + struct rockchip_usb2phy *priv = dev_get_priv(parent); + const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg; + + /* turn on 480m clk output if it is off */ + if (!property_enabled(priv->reg_base, &phy_cfg->clkout_ctl)) { + property_enable(priv->reg_base, &phy_cfg->clkout_ctl, true); + + /* waiting for the clk become stable */ + usleep_range(1200, 1300); + } + + return 0; +} + +/** + * disable() - Disable a clock. + * @clk: The clock to manipulate. + * + * Return: zero on success, or -ve error code. + */ +int rockchip_usb2phy_clk_disable(struct clk *clk) +{ + struct udevice *parent = dev_get_parent(clk->dev); + struct rockchip_usb2phy *priv = dev_get_priv(parent); + const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg; + + /* turn off 480m clk output */ + property_enable(priv->reg_base, &phy_cfg->clkout_ctl, false); + + return 0; +} + static struct clk_ops rockchip_usb2phy_clk_ops = { + .enable = rockchip_usb2phy_clk_enable, + .disable = rockchip_usb2phy_clk_disable, + .round_rate = rockchip_usb2phy_clk_round_rate };
static int rockchip_usb2phy_probe(struct udevice *dev) @@ -254,8 +323,11 @@ static int rockchip_usb2phy_bind(struct udevice *dev)
if (!ret) { node = dev_ofnode(dev); - name = ofnode_get_name(node); - dev_dbg(dev, "clk for node %s\n", name); + name = "clk_usbphy_480m"; + dev_read_string_index(dev, "clock-output-names", 0, &name); + + dev_dbg(dev, "clk %s for node %s\n", name, ofnode_get_name(node)); + ret = device_bind_driver_to_node(dev, "rockchip_usb2phy_clock", name, node, &usb2phy_dev); if (ret) { @@ -270,6 +342,7 @@ static int rockchip_usb2phy_bind(struct udevice *dev) static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = { { .reg = 0xe450, + .clkout_ctl = { 0xe450, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0xe454, 1, 0, 2, 1 }, @@ -291,6 +364,7 @@ static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = { }, { .reg = 0xe460, + .clkout_ctl = { 0xe460, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0xe464, 1, 0, 2, 1 },

On 6/4/23 10:13, Xavier Drudis Ferran wrote:
This clock doesn't seem needed but appears in a phandle list used by ehci-generic.c to bulk enable it. The phandle list comes from linux, where it is needed for suspend/resume to work [1].
My tests give the same results with or without this patch, but Marek Vasut found it weird to declare an empty clk_ops [2].
So I adapted the code from linux 6.1-rc8 so that it hopefully works if it ever has some user. For now, without real use, it seems to at least not give any errors when called.
Link: [1] https://lkml.kernel.org/lkml/1731551.Q6cHK6n5ZM@phil/T/ [2] https://patchwork.ozlabs.org/project/uboot/patch/Y5IWpjYLB4aXMy9o@localhost/
Cc: Simon Glass sjg@chromium.org Cc: Philipp Tomsich philipp.tomsich@vrull.eu Cc: Kever Yang kever.yang@rock-chips.com Cc: Lukasz Majewski lukma@denx.de Cc: Sean Anderson seanga2@gmail.com Cc: Marek Vasut marex@denx.de Cc: Christoph Fritz chf.fritz@googlemail.com Cc: Jagan Teki jagan@amarulasolutions.com
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat
v6: just retested over current next branch and some corrections to message and headers (no changes to code).
v5: ignores the return value from property_enable() which is not an error code in U-Boot (unlike in linux). This avoid a false failure of rockchip_usb2phy_clk_disable() that interfered with clock disable and appeared to cause hang or reset.
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 2f31350134..451841b025 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -55,6 +55,7 @@ struct rockchip_usb2phy_port_cfg {
struct rockchip_usb2phy_cfg { unsigned int reg;
- struct usb2phy_reg clkout_ctl; const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; };
@@ -76,6 +77,18 @@ static inline int property_enable(void *reg_base, return writel(val, reg_base + reg->offset); }
+static inline bool property_enabled(void *reg_base,
const struct usb2phy_reg *reg)
+{
- unsigned int tmp, orig;
- unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
- orig = readl(reg_base + reg->offset);
- tmp = (orig & mask) >> reg->bitstart;
Use FIELD_GET() macro if possible.
- return tmp != reg->disable;
+}
- static const struct rockchip_usb2phy_port_cfg *us2phy_get_port(struct phy *phy) {
@@ -168,7 +181,63 @@ static struct phy_ops rockchip_usb2phy_ops = { .of_xlate = rockchip_usb2phy_of_xlate, };
[...]

Thanks for looking at this.
El Sun, Jun 04, 2023 at 11:33:21AM +0200, Marek Vasut deia:
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 2f31350134..451841b025 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -55,6 +55,7 @@ struct rockchip_usb2phy_port_cfg { struct rockchip_usb2phy_cfg { unsigned int reg;
- struct usb2phy_reg clkout_ctl; const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; };
@@ -76,6 +77,18 @@ static inline int property_enable(void *reg_base, return writel(val, reg_base + reg->offset); } +static inline bool property_enabled(void *reg_base,
const struct usb2phy_reg *reg)
+{
- unsigned int tmp, orig;
- unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
- orig = readl(reg_base + reg->offset);
- tmp = (orig & mask) >> reg->bitstart;
Use FIELD_GET() macro if possible.
It would be possible, but it seems to require a constant mask. Now the mask is read from a cfg struct, so it's not constant. Currently the mask bitend and bitstart are really always the same value (4 and 4) for all (2) SOCs, so I could change the code to make it a constant and use FIELD_GET(), but I'd see two drawbacks:
- It makes code more different than needed from linux drivers/phy/rockchip/phy-rockchip-inno-usb2.c
- It will stop working if we ever support rk3366 here, the mask there is bit 15.
So I'd rather leave it as it is.
But you made me realise I was missing the clkout_ctl struct for rk3568, so I'll copy from linux in v7. I can't test it, though.
Thank you.

On Sun, Jun 4, 2023 at 1:42 PM Xavier Drudis Ferran xdrudis@tinet.cat wrote:
EHCI probing in Rock pi 4 currently fails.
Add a clock driver for usb2phy so that probing EHCI does not fail when missing one of the clocks in the bundle for usb_host0_ehci, since usb2phy is UCLASS_PHY but not UCLASS_CLK.
Xavier Drudis Ferran (2): arm: dts: rockchip: rk3399: usb: ehci: Fix EHCI probe in rk3399 to access peripherals by USB 2. arm: rk3399: usb2phy: phy-rockchip-inno-usb2.c: Implement operations for the 480MHz usb2phy clock in rk3399.
Please note that commit head on both the patches seems improper to me.
Commit body looks fine, but the head should start
phy: rockchip-inno-usb2: Add usb2phy clock provider of 480MHz clock phy: rockchip-inno-usb2: Implement clock operations for usb2phy clock
Thanks, Jagan.

El Mon, Jun 05, 2023 at 08:11:07AM +0530, Jagan Teki deia:
On Sun, Jun 4, 2023 at 1:42 PM Xavier Drudis Ferran xdrudis@tinet.cat wrote:
EHCI probing in Rock pi 4 currently fails.
Add a clock driver for usb2phy so that probing EHCI does not fail when missing one of the clocks in the bundle for usb_host0_ehci, since usb2phy is UCLASS_PHY but not UCLASS_CLK.
Xavier Drudis Ferran (2): arm: dts: rockchip: rk3399: usb: ehci: Fix EHCI probe in rk3399 to access peripherals by USB 2. arm: rk3399: usb2phy: phy-rockchip-inno-usb2.c: Implement operations for the 480MHz usb2phy clock in rk3399.
Please note that commit head on both the patches seems improper to me.
Commit body looks fine, but the head should start
phy: rockchip-inno-usb2: Add usb2phy clock provider of 480MHz clock phy: rockchip-inno-usb2: Implement clock operations for usb2phy clock
Thanks, Jagan.
Done, thank you. I hope it's right now.
participants (3)
-
Jagan Teki
-
Marek Vasut
-
Xavier Drudis Ferran