On 18-03-2025 01:12, Thinh Nguyen wrote:
On Mon, Mar 17, 2025, Mike Looijmans wrote:
On 14-03-2025 22:14, Thinh Nguyen wrote:It's not obvious to me if this is an error in Xilinx documentation, the
On Fri, Mar 14, 2025, Mike Looijmans wrote:I don't understand your question. What "programming flow" are you referring
Set the gpio to "high" on acquisition, instead of acquiring it in lowHow does this affect the current programming flow beside preventing a
state and then immediately setting it high again. This prevents a
short "spike" on the reset signal.
spike to the reset signal?
to?
driver issue, or whether this is found through experiment. Since I don't
have the info of this platform, it would help to know where the source
of error is so we can document this in the code or change-log.
It's a bug in the driver, found through code inspection.
The reset GPIO here is to control the reset signal to an external, usually ULPI PHY, chip. This external chip is not part of the Xilinx hardware.
The reset sequence was just plain wrong, the issue is almost the same as theDo we need a fix tag and add to stable then?
That would be appropriate I think.
one described in this commit:Then can we remove it?
e0183b974d30 "net: mdiobus: Prevent spike on MDIO bus reset signal"
Note that I see this high-low-high-low double reset toggle in many Xilinx
software drivers, they seem to teach that at the Xilinx academy or so.
Now you mention it, the comment never made any sense anyway.Signed-off-by: Mike Looijmans <mike.looijmans@xxxxxxxx>Does the comment above still apply?
---
drivers/usb/dwc3/dwc3-xilinx.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index a33a42ba0249..a159a511483b 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -207,7 +207,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
skip_usb3_phy:
/* ulpi reset via gpio-modepin or gpio-framework driver */
- reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(reset_gpio)) {
return dev_err_probe(dev, PTR_ERR(reset_gpio),
"Failed to request reset GPIO\n");
@@ -215,7 +215,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
if (reset_gpio) {
/* Toggle ulpi to reset the phy. */
Removing would be better, yes. I'll make a v2 patch.
But why do we need 2 calls to usleep_range? From just looking at thisYes, this is the "reset active" time.- gpiod_set_value_cansleep(reset_gpio, 1);Do we still need this usleep_range here?
usleep_range(5000, 10000);
here, it appears that the first was intended for the removed
gpiod_set_value_cansleep(reset_gpio, 1). If this "reset active" time is
needed irrespective of the existent reset_gpio, then shouldn't it be set
outside of this if statement?
It helps to see the whole thing instead of just the patch.
If I omit error handling and comments then the original code reads:
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (reset_gpio) {
gpiod_set_value_cansleep(reset_gpio, 1);
usleep_range(5000, 10000);
gpiod_set_value_cansleep(reset_gpio, 0);
usleep_range(5000, 10000);
}
So the gpio is acquired in a LOW state and then, without delay, is set to a high state again. This causes the "spike" I'm mentioning here. The correct procedure is to acquire it in the HIGH state immediately, so the sequence becomes:
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (reset_gpio) {
usleep_range(5000, 10000);
gpiod_set_value_cansleep(reset_gpio, 0);
usleep_range(5000, 10000);
}
This patch does exactly that.