[PATCH] usb: dwc3: Always deassert xilinx resets

Pandey, Radhey Shyam radhey.shyam.pandey at amd.com
Thu Jan 8 22:01:43 PST 2026


[AMD Official Use Only - AMD Internal Distribution Only]

> -----Original Message-----
> From: Thinh Nguyen <Thinh.Nguyen at synopsys.com>
> Sent: Friday, January 9, 2026 6:19 AM
> To: Sean Anderson <sean.anderson at linux.dev>
> Cc: Thinh Nguyen <Thinh.Nguyen at synopsys.com>; open list:DESIGNWARE
> USB3 DRD IP DRIVER <linux-usb at vger.kernel.org>; Frager, Neal
> <neal.frager at amd.com>; Simek, Michal <michal.simek at amd.com>; open list
> <linux-kernel at vger.kernel.org>; moderated list:ARM/ZYNQ ARCHITECTURE
> <linux-arm-kernel at lists.infradead.org>; Philipp Zabel <p.zabel at pengutronix.de>;
> Pandey, Radhey Shyam <radhey.shyam.pandey at amd.com>; Greg Kroah-Hartman
> <gregkh at linuxfoundation.org>
> Subject: Re: [PATCH] usb: dwc3: Always deassert xilinx resets
>
> On Tue, Jan 06, 2026, Sean Anderson wrote:
> > If we don't have a usb3 phy we don't need to assert the core resets.
> > Deassert them even if we didn't assert them to support booting when
> > the bootloader never released the core from reset.
Is it a customized bootloader ? i.e it assert reset but don't deassert.

I think ideally core /APB reset should be done independent on
MAC 2.0/3.0 configuration. Not sure where the recommendation is
coming from to only do it for 3.0 MAC. Let me check the IP spec.
Thinh: Please chime in with your thoughts.


> >
>
> > Signed-off-by: Sean Anderson <sean.anderson at linux.dev>
> > ---
> >
> >  drivers/usb/dwc3/dwc3-xilinx.c | 67
> > ++++++++++++++++------------------
> >  1 file changed, 32 insertions(+), 35 deletions(-)
> >
>
> This sounds like a fix. Does it need to be Cc Stable and backported?
>
> Regardless,
>
> Acked-by: Thinh Nguyen <Thinh.Nguyen at synopsys.com>
>
> Thanks,
> Thinh
>
> > diff --git a/drivers/usb/dwc3/dwc3-xilinx.c
> > b/drivers/usb/dwc3/dwc3-xilinx.c index 0a8c47876ff9..f41b0da5e89d
> > 100644
> > --- a/drivers/usb/dwc3/dwc3-xilinx.c
> > +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> > @@ -132,21 +132,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx
> *priv_data)
> >             goto err;
> >     }
> >
> > -   /*
> > -    * The following core resets are not required unless a USB3 PHY
> > -    * is used, and the subsequent register settings are not required
> > -    * unless a core reset is performed (they should be set properly
> > -    * by the first-stage boot loader, but may be reverted by a core
> > -    * reset). They may also break the configuration if USB3 is actually
> > -    * in use but the usb3-phy entry is missing from the device tree.
> > -    * Therefore, skip these operations in this case.
> > -    */
> > -   if (!priv_data->usb3_phy) {
> > -           /* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
> > -           writel(PIPE_CLK_DESELECT, priv_data->regs +
> XLNX_USB_FPD_PIPE_CLK);
> > -           goto skip_usb3_phy;
> > -   }
> > -
> >     crst = devm_reset_control_get_exclusive(dev, "usb_crst");
> >     if (IS_ERR(crst)) {
> >             ret = PTR_ERR(crst);
> > @@ -171,22 +156,31 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx
> *priv_data)
> >             goto err;
> >     }
> >
> > -   ret = reset_control_assert(crst);
> > -   if (ret < 0) {
> > -           dev_err(dev, "Failed to assert core reset\n");
> > -           goto err;
> > -   }
> > +   /*
> > +    * Asserting the core resets is not required unless a USB3 PHY is used.
> > +    * They may also break the configuration if USB3 is actually in use but
> > +    * the usb3-phy entry is missing from the device tree. Therefore, skip
> > +    * a full reset cycle and just deassert the resets if the phy is
> > +    * absent.
> > +    */
> > +   if (priv_data->usb3_phy) {
> > +           ret = reset_control_assert(crst);
> > +           if (ret < 0) {
> > +                   dev_err(dev, "Failed to assert core reset\n");
> > +                   goto err;
> > +           }
> >
> > -   ret = reset_control_assert(hibrst);
> > -   if (ret < 0) {
> > -           dev_err(dev, "Failed to assert hibernation reset\n");
> > -           goto err;
> > -   }
> > +           ret = reset_control_assert(hibrst);
> > +           if (ret < 0) {
> > +                   dev_err(dev, "Failed to assert hibernation reset\n");
> > +                   goto err;
> > +           }
> >
> > -   ret = reset_control_assert(apbrst);
> > -   if (ret < 0) {
> > -           dev_err(dev, "Failed to assert APB reset\n");
> > -           goto err;
> > +           ret = reset_control_assert(apbrst);
> > +           if (ret < 0) {
> > +                   dev_err(dev, "Failed to assert APB reset\n");
> > +                   goto err;
> > +           }
> >     }
> >
> >     ret = phy_init(priv_data->usb3_phy); @@ -201,11 +195,15 @@ static
> > int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
> >             goto err;
> >     }
> >
> > -   /* Set PIPE Power Present signal in FPD Power Present Register*/
> > -   writel(FPD_POWER_PRSNT_OPTION, priv_data->regs +
> XLNX_USB_FPD_POWER_PRSNT);
> > -
> > -   /* Set the PIPE Clock Select bit in FPD PIPE Clock register */
> > -   writel(PIPE_CLK_SELECT, priv_data->regs +
> XLNX_USB_FPD_PIPE_CLK);
> > +   if (priv_data->usb3_phy) {
> > +           /* Set PIPE Power Present signal in FPD Power Present Register*/
> > +           writel(FPD_POWER_PRSNT_OPTION, priv_data->regs +
> XLNX_USB_FPD_POWER_PRSNT);
> > +           /* Set the PIPE Clock Select bit in FPD PIPE Clock register */
> > +           writel(PIPE_CLK_SELECT, priv_data->regs +
> XLNX_USB_FPD_PIPE_CLK);
> > +   } else {
> > +           /* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
> > +           writel(PIPE_CLK_DESELECT, priv_data->regs +
> XLNX_USB_FPD_PIPE_CLK);
> > +   }
> >
> >     ret = reset_control_deassert(crst);
> >     if (ret < 0) {
> > @@ -225,7 +223,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx
> *priv_data)
> >             goto err;
> >     }
> >
> > -skip_usb3_phy:
> >     /* ulpi reset via gpio-modepin or gpio-framework driver */
> >     reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> >     if (IS_ERR(reset_gpio)) {
> > --
> > 2.35.1.1320.gc452695387.dirty
> >


More information about the linux-arm-kernel mailing list